转载注明出处 https://blog.csdn.net/qq_39071530/article/details/84890362
github地址 https://github.com/esmusssein777/designpatterns
设计模式目录 https://blog.csdn.net/qq_39071530/article/details/84849070
OO真正的精华,工厂模式。
在实例化的时候除了使用过new操作符之外,还可以使用工厂模式制造对象。当然在工厂模式里面代码是一样的,并不会少。
那么什么时候用到呢?
当实例化不希望他公开的进行时。还有不希望初始化的时候造成耦合问题的时候。
说了这么些,还不如写点代码。。。。
这里就直接用书上的代码好了。
假设你有一个Pizza店,并且你有很多种类型的Pizza,那么你会这样写代码:
Pizza orderPizza(String type){
Pizza pizza;
if(type.equals("chesse")){
pizza = new CheesePizza();
}else if(type.equals("greek")){
pizza = new GreekPizza();
}else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
当你看到下面这样的代码时就要小心了
if(type.equals("chesse")){
pizza = new CheesePizza();
}else if(type.equals("greek")){
pizza = new GreekPizza();
}else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
因为当你以后改变条件的时候需要在原有的代码上修改,或者需求的变化一改再改。
我们就需要用工厂来帮助我们制造对象。
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
这是简单工厂。其实并不算是一种设计模式。代码量并没有变化,只是把创建Pizza的代码包装进一个类后,当以后实现改变的话,只需要修改这个类即可。我们正需要做的就是把实例化的过程,从客户的代码中删除。
当你使用了很多的if-else的时候你就要考虑一下是否使用简单工厂。
工厂模式
用书上的例子,当很多的加盟店加入到披萨店时,就需要使用工厂模式。
特点:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
最简单的理解就是,当下面的代码又有很多个的时候。
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
不同的子类对应的createPizza不同的时候我们就是要用到工厂模式。举例来说就是你开的麻辣烫店在不同的地方要有不同的口味。比如开在重庆就要辣,开在海南就要清淡。
所以不同的地方createPizza不一样。于是就把createPizza方法推迟到子类去进行。
但是简单工厂并不能继承。
于是我们将代码写成这样。
public abstract class PizzaStore {
//这里定义一个工厂方法
abstract Pizza createPizza(String item);
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
System.out.println("--- Making a " + pizza.getName() + " ---");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
里面最重要的是记住这行代码
abstract Pizza createPizza(String item);
这将具体的创建推迟到了子类
public class ChicagoPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new ChicagoStyleCheesePizza();
} else if (item.equals("veggie")) {
return new ChicagoStyleVeggiePizza();
} else if (item.equals("clam")) {
return new ChicagoStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new ChicagoStylePepperoniPizza();
} else return null;
}
}
不同的子类有不同的方法。
划重点!!
所有的工厂模式都用来封装对象的创建。工厂方法模式让子类来决定创建的对象是什么,来达到将对象创建的过程封装的目的。
首先是总的披萨店,里面有create和order两个方法。但是每个地方的create方法不一样。
于是我们将create转为abstract,由子类继承的时候实现具体的食物。
再将具体创建那个对象封装进去。
这个就是工厂模式。
你可以想象一下如果不用工厂模式需要多少个 if-else 来判断创建那个类。
模式都是为我们减轻负担的。
抽象工厂模式
提供了一个接口,用于创建相关或依赖的对象家族。而不需要明确的指定具体类。
具体的例子用书的,当加盟店的原料也需要工厂来生产时,不同地方的原料不一样。
于是用抽象工厂模式,我们先来定义一个接口,就是需要原料的接口
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
我们纽约的原料工厂是这样的,继承上面的接口、
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
public Veggies[] createVeggies() {
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
我们接下来是重新的准备披萨。
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
Veggies[] veggies;
Pepperoni pepperoni;
Cheese cheese;
Clams clam;
public abstract void prepare();
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cut the pizza into diagonal slices");
}
void box() {
System.out.println("Place the pizza into offical PizzaStore box");
}
void setName(String name) {
this.name = name;
}
String getName() {
return name;
}
public String toString() {
return name + ((dough != null)?" Dough:"+dough.getClass().getName():"")
+ ((sauce != null)?" Sauce:" + sauce.getClass().getName():"")
+ ((cheese != null)?" Cheese:" + cheese.getClass().getName():"")
+ ((clam != null)?" Clam:" + clam.getClass().getName():"");
}
}
public abstract void prepare();我们将准备的方法设为抽象方法。
当我们需要准备一个纽约的披萨时 。
‘我们继承该类
public class CheesePizza extends Pizza {
//这里组合了一个PizzaIngredientFactory对象的引用,用于提供不同的原料
PizzaIngredientFactory ingredientFactory;
/**
* 通过传入一个PizzaIngredientFactory原料工厂,我们可以在制作Pizza的时候动态的产生所需要的原料
* @param ingredientFactory
*/
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
像dough = ingredientFactory.createDough()这样的代码完美的体现了针对接口编程。
我们完全不需要要关心我们的原料工厂是哪一种。只需要在实现的时候将他传进来即可。
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if (item.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");
} else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
} else if (item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza");
}
return pizza;
}
}
这里简单的画一下
抽象工厂的每个方法实际上看起来都像是工厂方法。就像每一个createDough()和createSauce()。