简介
在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。
举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。
又比如某个接口有很多实现类,如果使用new的方式创建对象,就需要用户了解具体应该使用哪个类,如果每个类实例化的参数还不一样,对用户来说就非常麻烦。此时工厂模式就派上了用处,用户只需告诉工厂自己需要哪种对象,由工厂来判断应当创建哪种对象并返回给用户。
Spring 中bean的创建就是典型的工厂模式,他的顶级接口是 BeanFactory,下图是这个工厂的继承层次关系:
工厂模式又可以分为简单工厂,抽象工厂方法和抽象工厂三种类型。 GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
简单工厂
我们经常一些功能类似的类,所以我们的思路是对进行抽象,使用接口暴露公共的方法,使用抽象类来提供公共的实现。
这些功能类似的类的实例化成为了一个问题,每个类的构造方法参数还不一样,每次 new 对象很麻烦,封装成简单工厂模式。
抽象工厂方法
简单工厂模式不利于拓展,违背了开闭原则,每次添加一个类,都要修改工厂类(如果是工厂类和业务类是两个小伙伴分开写的,那不是要花很多时间来沟通…),所以就有工厂方法模式,其原理就是对简单工厂也进行抽象。
抽象工厂
第 4 个问题:功能类似的产品我们进行 3 层抽象,针对每个产品我们还抽象出了 2 层的工厂类,代码量一下子增加了很多。
但是我们在某个具体的业务场景中,不单单是只实例化一个类啊。举一个例子,要造一个汽车,汽车由多个部件组成,如发动机、轮子、方向盘等等,这就需要汽车厂能同时建造这多种部件,组装成汽车。
这就是抽象工厂模式。简单来说,可以把有一些有联系或者相近的产品,放到一个工厂去生产,没有必要单独再开一个工厂了。
例如,现在要生产便宜的汽车和昂贵的汽车,每种汽车用的零件类型也有昂贵和便宜的区别:代码: github
|
|
|
|
|
|
部件1:
部件2:
用来调用具体工厂并进行汽车组装的类:
测试:
运行结果:
总结
- 三种工厂的实现是越来越复杂的
- 简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦
- 工厂模式无法解决产品族和产品等级结构的问题
- 抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。
参考
https://www.ibm.com/developerworks/cn/java/designpattern/factory/
https://www.zhihu.com/question/24843188?sort=created
http://www.runoob.com/design-pattern/abstract-factory-pattern.html