Version: Next
工厂方法 Factory Method
源发问题
希望对不同类型的创建对象拥有共同的使用方式
解决方案
在抽象类中定义用于创建对象的接口,让子类决定实例化哪个类。如类图所示,抽象类Creator
定义抽象方法factoryMethod
,该方法被具体子类覆盖后创建一个product
的具体产品,具体产品对象在Creator
的AnOperation
方法中被product
的声名引用。虽然对产品实例化的过程实在子类中进行的,但在AnOperation
中通过product
对具体产品的使用都相同
定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
可以看作是简单工厂模式中的StaticSimpleFactory
不只一种,而是有好几种不太一样的具体工厂,再它们头上再抽一个抽象工厂(Creator
)出来,这样就可以在原本封装实例化的基础上更加发挥多态性的威力,体现一种共同的创建Product(Pizza)的策略或者方法
UML类图
代码
- 先前简单工厂模式中的
PizzaStore
类变为了抽象类,由派生的子类延时new对象
public abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
public class ChicagoPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
pizza = new ChicagoStyleCheesePizza();
}else if ("greek".equals(type)) {
pizza = new ChicagoStyleGreekPizza();
}else if ("pepperoni".equals(type)){
pizza = new ChicagoStylePepperoniPizza();
}else if ("clam".equals(type)){
pizza = new ChicagoStyleClamPizza();
}
return pizza;
}
}
public class NYPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
pizza = new NYStyleCheesePizza();
}else if ("greek".equals(type)) {
pizza = new NYStyleGreekPizza();
}else if ("pepperoni".equals(type)){
pizza = new NYStylePepperoniPizza();
}else if ("clam".equals(type)){
pizza = new NYStyleClamPizza();
}
return pizza;
}
}
这些继承抽象类
PizzaStore
的具体类中,完成对具体产品(ChicagoxxxPizza
orNYxxxPizza
)的创建public class NYPizzaStore extends PizzaStore {@Overridepublic Pizza createPizza(String type) {Pizza pizza = null;if ("cheese".equals(type)) {pizza = new NYStyleCheesePizza();}else if ("greek".equals(type)) {pizza = new NYStyleGreekPizza();}else if ("pepperoni".equals(type)){pizza = new NYStylePepperoniPizza();}else if ("clam".equals(type)){pizza = new NYStyleClamPizza();}return pizza;}}public class ChicagoPizzaStore extends PizzaStore {@Overridepublic Pizza createPizza(String type) {Pizza pizza = null;if ("cheese".equals(type)) {pizza = new ChicagoStyleCheesePizza();}else if ("greek".equals(type)) {pizza = new ChicagoStyleGreekPizza();}else if ("pepperoni".equals(type)){pizza = new ChicagoStylePepperoniPizza();}else if ("clam".equals(type)){pizza = new ChicagoStyleClamPizza();}return pizza;}}
而具体的产品(各种具体披萨)都派生自抽象产品(抽象类
Pizza
)public class ChicagoStyleGreekPizza extends Pizza {@Overridepublic void prepare() {System.out.println("Chicago style greek pizza preparing...");}}
- 客户端使用时,声名抽象的
Creator
(PizzaStore),实例化时使用具体的ConcreteCreator
,调用工厂方法,生产具体产品(XxxPizza)
public class Test {
public static void main(String[] args) {
PizzaStore pizzaStore = new NYPizzaStore();
pizzaStore.orderPizza("cheese");
pizzaStore = new ChicagoPizzaStore();
pizzaStore.orderPizza("cheese");
}
}
优缺点
- 优点
- 子类只关心如何实现抽象方法来创建一个具体对象,之后便自动拥有了该对象的扩展功能,即为子类提供一个挂钩以获得对象功能的扩展版本
- 缺点
- 在
Creator
和Product
下容易产生平行类,即每个具体的Creator
子类对应产生一个Product
下的具体子类对象
- 在