什么是工厂模式
工厂方法模式定义了一个创建对象的接口,但由子类来决定要实例化那个类。工厂方法让类把实例化推迟到了子类。
为什么要有工厂模式
书中以pizza店制作pizza为例子,假设不用工厂模式,在制作pizza阶段我们需要这样去实例化类:
Pizza orderPizza(String type) {Pizza pizza;// 基于pizza的类型,实例化具体的类,这里的每个pizza都需要实现Pizza接口if (type.equals("cheess")) {pizza = new CheesePizza();} else if (type.equals("greek")) {pizza = new GreekPizza();}// pizza的前期准备pizza.prepare();pizza.bake();return pizza;
}
上述代码不符合开闭原则,一旦pizza店改变pizza的供应,则需要修改上述代码
简单工厂模式
简单工厂模式并不是一种设计模式,而是一种编程习惯,定义一个工厂类,这个类封装所有披萨的对象创建,pizza店客户端中不会进行实例化
代码如下:
// 简单工厂代码
public Pizza SimplePizzaFactory {public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals("cheess")) {pizza = new CheesePizza();} else if (type.equals("greek")) {pizza = new GreekPizza();}}
}// 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的前期准备pizza.prepare();pizza.bake();return pizza;}
}
简单工厂模式的类图:
简单工厂模式的优点:
- 将变化的部分抽离出来独立形成工厂,避免在客户端直接创建
简单工厂模式的缺点:
- 简单工厂只是提供了封装对象创建的一种方式,但没有提供工厂方法的弹性,因为它没有办法改变正在创建的产品。
工厂模式
如果pizza店引入了加盟商,加盟商对于pizza需要有一些自己的定制化需求,而上面的简单工厂模式,则不符合这种需求,需要引入工厂模式。
具体代码:
1、定义pizza店接口
public abstract class PizzaStore {public Pizza orderPizza(String type) {Pizza pizza;pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}protected abstract Pizza createPizza(String type); // 交给子类进行实例化
}
2、 抽象pizza的制作流程
public abstract class Pizza {String name;String dough;void prepare() {System.out.println("prepare finish");};void bake() {System.out.println("bake finish");};void cut() {System.out.println("cut finish");};void box() {System.out.println("box finish");};public String getName() {return name;};
}
3、定义加盟商的定制化需求
public class NYPizzaStore extends PizzaStore{@Overridepublic Pizza createPizza(String item) {if (item.equals("cheese")) {return new NYStyleCheesePizza();}else return null;}
}
4、定义加盟商所使用的pizza材料
public class NYStyleCheesePizza extends Pizza{public NYStyleCheesePizza() {String name = "NY Style pizza";String dough = "thin crust dough";String sauce = "Marinara Sauce";}
}
5、main函数执行
public class Main {public static void main(String[] args) {PizzaStore nyStore = new NYPizzaStore();Pizza pizza = nyStore.orderPizza("cheese");}}
执行结果:
prepare finish
bake finish
cut finish
box finish
工厂模式的类图:
工厂模式中引入的设计原则:
- 依赖倒置原则:依赖抽象,而不应该依赖具体类
遵循依赖倒置设计原则的指南:
- 变量不应该持有到具体类的引用
- 类不应该派生自具体类
- 方法不应该覆盖任何基类的已实现方法
(以上指南并不是铁律,要看具体的场景来遵守)
抽象工厂模式
抽象工厂模式提供一个接口来创建相关或依赖对象的家族,而并不需要指定具体的类
比较工厂方法与抽象工厂方法:
工厂方法:
抽象工厂方法:
区别:
- 工厂方法中只会提供一个抽象接口,接口的实现交给各个工厂去做,抽象类只会知道是制作一个pizza。
- 抽象工厂是把工厂方法中的接口给拆开了,提供抽象接口的组合。会感知到制作pizza的抽象信息。
- 抽象方法中对于每一个抽象接口的实现,利用了工厂方法的思路。