目录
前言
为什么需要工厂模式?
当使用new实例化一个类时,使用的是实现,而不是接口,代码捆绑着具体类会导致代码更脆弱缺乏弹性,使用松耦合的OO模式可以得到解脱。
1、简单工厂
简单工厂并不是一种设计模式,因为只是简单的把创建对象的代码封装起来,封装对象的创建,处理创建对象的细节
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;
}
}
2、静态工厂
利用静态方法定义一个简单的工厂。优点:不需要创建工厂类的实例化。缺点:不能通过继承改变创建方法行为。可以简单理解为在简单工厂的基础上添加一个静态关键字
public class SimplePizzaFactory {
public static 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;
}
}
3、工厂方法模式(使用继承)
在父类定义了一个创建对象的接口方法,通过让子类决定创建的对象是什么,来达到让对象创建的过程封装的目的。工厂方法让类把实例化推迟到子类。工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样客户程序中超类的代码就和子类对象的创建部分解耦了
4、抽象工厂(使用组合)
提供一个接口,用于创建相关或依赖对象的家族,而不需要指明具体的类
- 简单工厂vs工厂模式
简单工厂把全部的事情在一个地方做完了,而工厂模式是一个创建框架,让子类决定如何实现
- 抽象工厂vs工厂模式
抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口
工厂方法使用继承,抽象工厂使用组合
工厂方法只是用来创建一种产品,而抽象工厂创建的是一个产品家族
使用工厂模式意味着需要扩展一个类并覆盖它的工厂方法。抽象工厂提供了一个创建产品家族的抽象类型,类型的子类定义了产品生产的方式
先来定义一个接口PizzaIngredientFactory,他定义了一系列的创建Pizza材料的方法
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();
}
}
Pizza类
public abstract class Pizza {
String name;
// 每个披萨都持有一组在准备时会用到的原料
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clams;
// 现在把prepare()方法声明成抽象。在这个方法中,我们需要收集披萨所需的原料,而这些原料当然是来自原料工厂了。
abstract void prepare();
// 其他的方法保持不动
void bake(){
// ...
}
void cut(){
// ...
}
void box(){
// ...
}
}
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
// 要制作披萨,需要工厂提供原料。
// 所以每个披萨类都需要从构造器参数中得到一个工厂,并把这个工厂存储在一个实例变量中。
public CheesePizza(PizzaIngredientFactory ingredientFactory){
this.ingredientFactory = ingredientFactory;
}
@Override
void prepare() {
// prepare()方法一步一步地创建芝士披萨,每当需要原料时,就跟工厂要。
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
Pizza商店
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
// 现在createPizza()方法从工厂对象中移回PizzaStore
pizza = createPizza(type);
// 这些都没变
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
// 现在把工厂对象移到这个方法中
// 在PizzaStore里,“工厂方法”现在是抽象的
abstract Pizza createPizza(String type);
}
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;
}
}
PizzaStore实现为工厂方法,因为我们需要根据区域变化创建产品。通过工厂方法,每个区域都有自己的具体工厂,他们都知道如何制作适合该区域的披萨。
因为我们需要创建一个产品家族(也就是原料),我们把PizzaIngredientFactory实现为抽象工厂。每个子类都使用其区域的供货商来实现这些原料。
工厂方法使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象。工厂方法允许类将实例化延迟到子类进行。
抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴露出来的方法中。抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
所有工厂都是用来封装对象的创建。所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
参考:
《head first 设计模式》