工厂方法模式定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使类的实例化推迟到其子类
下面看一个示例:一个简单工厂实现的PizzaFactory
public interface Pizza {
}
public class ChinesePizza implements Pizza {
}
public class NewYorkPizza implements Pizza {
}
public class PizzaFactory {
public Pizza createPizza(String type){
if(type.equals("China"))
return new ChinesePizza();
else if(type.equals("NewYork"))
return new NewYorkPizza();
return null;
}
}
public class People {
public void getPizza(){
PizzaFactory pizzaFactory = new PizzaFactory();
Pizza pizza = pizzaFactory.createPizza("China");
}
}
此时如果想要添加一种新的Pizza类,我们必须要修改PizzaFactory以便可以通过工厂类生成新的Pizza类的实例,这明显违背了开闭原则,因为我们不得不修改现有代码以适应变化
PizzaFactory负责生成所有Pizza类的实例,如果只负责生成一种Pizza类的实例,就可以避免每次添加新的类型都不得不修改已有代码逻辑,缺点就是类的个数会变得更多,相应得代码逻辑将变得更复杂
public class ChinesePizzaFactory {
public Pizza createPizza(){
return new ChinesePizza();
}
}
public class NewYorkPizzaFactory {
public Pizza createPizza(){
return new NewYorkPizza();
}
}
public class People {
public void getPizza(){
ChinesePizzaFactory chinesePizzaFactory = new ChinesePizzaFactory();
Pizza chinesePizza = chinesePizzaFactory.createPizza();
NewYorkPizzaFactory newYorkPizzaFactory = new NewYorkPizzaFactory();
Pizza newYorkPizza = newYorkPizzaFactory.createPizza();
}
}
我们很容易就会想到从ChinesePizzaFactory和NewYorkPizzaFactory抽象出公共父类并把共有方法放置其中
public abstract class PizzaFactory {
public abstract Pizza createPizza();
}
public class ChinesePizzaFactory extends PizzaFactory {
public Pizza createPizza(){
return new ChinesePizza();
}
}
public class NewYorkPizzaFactory extends PizzaFactory {
public Pizza createPizza(){
return new NewYorkPizza();
}
}
public class People {
public void getPizza(){
PizzaFactory pizzaFactory = new ChinesePizzaFactory();
Pizza chinesePizza = pizzaFactory.createPizza();
}
}
可以看到现在PizzaFactory类及其子类的结构完全符合工厂方法模式的定义
判断生成何种Pizza类实例的逻辑依然存在,仅仅是将其从工厂类(PizzaFactory)移动至了调用方(People),但是调用方仅需耦合自己需要的ChinesePizzaFactory类,而不必像工厂类那样必须负责所有Pizza类的实例化,耦合度还是有所降低的
下面的示例就更清晰了
public abstract class PizzaFactory {
public abstract Pizza createPizza();
private void prepare(){}
public final Pizza getPizza(){
prepare();
Pizza pizza = this.createPizza();
pack(pizza);
return pizza;
}
private void pack(Pizza pizza){}
}
public class People {
public void getPizza(){
PizzaFactory pizzaFactory = new ChinesePizzaFactory();
Pizza chinesePizza = pizzaFactory.getPizza();
}
}