设计模式之工厂模式
2021 algorithm一般情况下,工厂模式可以分为:简单工厂,工厂方法和抽象工厂。而简单工厂、工厂方法原理比较简单,在实际项目中也比较常用。
简单工厂
简单工厂(Simple Factory)就是将代码中负责创建对象的代码抽离到一个独立的类中,让这个类只处理创建对象的细节。
简单工厂是为了让类的职责更加单一、代码更加清晰。简单工厂其实不像一个设计模式,反而比较像一中编程习惯。
来自《Head First 设计模式》的代码实例:
Pizza orderPizza(String type) {
Pizza pizza;
// 创建Pizza对象的代码
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
return pizza;
}
我们将创建 Pizza 对象的代码抽离出来到 SimplePizzaFactory 类中。
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
return pizza;
}
}
再重新修改一下 Pizza 商店代码。
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String type) {
Pizza pizza;
// 通过使用简单工厂来创建披萨
pizza = factory.createPizza(type);
return pizza;
}
}
工厂方法
当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂。
《设计模式》中定义:一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到子类。
工厂方法的代码示例:https://github.com/chesterchenn/HFDP/tree/master/src/chapterd/b
使用工厂模式的情况
当创建逻辑比较复杂,我们就考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。何为创建逻辑比较复杂呢?下面两种情况:
-
第一种情况:类似规则配置解析的例子,代码中存在 if-else 分支判断,动态地根据不同的类型创建不同的对象。针对这种情况,我们就考虑使用工厂模式,将这一大坨 if-else 创建对象的代码抽离出来,放到工厂类中。
-
还有一种情况,尽管我们不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,比如前面提到的要组合其他类对象,做各种初始化操作。在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中。
工厂方法与简单工厂的差异
工厂方法的子类的确看起来很像简单工厂。简单工厂把全部事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。简单工厂可以将对象的创建封装起来,但是不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。
DI 容器
DI 容器叫依赖注入容器(Dependency Injection Container),也叫依赖注入框架。
DI 容器底层的设计思路是基于工厂模式的。DI 容器相当于一个大的工厂类,负责在程序启动的时候,根据配置事先创建好对象。当应用程序需要使用某个类对象的时候,直接从容器中获取即可。一个工厂类只负责某个类对象或者一组相关类的对象的创建,而 DI 容器负责的是整个应用中所有类对象的创建。
DI 容器的核心功能
DI 容器的核心功能一般有三个:配置解析,对象创建和对象生命周期管理。
配置解析
将需要由 DI 容器创建的类对象和创建类对象的必要信息,放到配置文件中。容器读取配置文件,根据配置文件提供的信息来创建对象。
对象创建
我们将所有的类对象创建放到一个工厂类中完成就可以了,比如 BeansFactory。避免每个类的创建一个工厂类,导致的类个数成倍增加。
对象的生命周期管理
简单工厂模式有两种实现方式,一种是每次都返回新创建的对象,另一种是每次都返回同一个事先创建好的对象,也就是所谓的单例对象。可以配置对象是否支持懒加载,还可以配置对象的 init-method 和 destroy-method 方法。
抽象工厂
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
其他
大部分工厂类都是以“Factory”结尾,工厂类中的创建对象的方法一般都是 create 开头,但都不是必须的。
参考链接
- Wiki: Factory method pattern
- 极客时间:设计模式之美-工厂模式(上)
- 《李建忠:C++ 设计模式》
- 《Head First 设计模式》