简单工厂
简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例。属于创建者模式。
简单工厂需要的元素
- 一系列产品的抽象,可以是抽象类或者是接口。
- 继承这个抽象类,或者实现这个接口的普通类。
- 一个通用的工厂,提供工厂方法(通常是静态方法)。这个工厂方法根据传进来的参数,返回对应的对象。
设计思路
为什么需要用这个方式呢?这个方式解决了什么问题?这个模式侧重点在哪儿?适用场景是什么?
通过工厂方法来获取对象,屏蔽了构建对象的过程。要知道,有的时候,构造方法也会是很复杂的,并且构造方法如果增加了参数,那么涉及到的代码就都要修改。而采用了工厂方法,将复杂的构造方法统一处理,调用者不需要关心这个对象具体构造的过程。同时,如果构造方法改造了,也只需要修改静态工厂方法即可。
这个模式的侧重点在于,创建对象或者获取对象的过程,在于屏蔽掉构造的细节。
适用于负责创建的对象比较少的场景,客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。
优缺点:
优点:只需要传入一个简单的参数就可以获取到对象。
缺点:增加新的产品依旧违背开闭原则。不易于拓展过于复杂的产品结构。
示意图
工厂方法模式
工厂方法模式是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法模式让类的实例化推迟到子类中进行。属于创建者模式。
工厂方法模式需要的元素
- 一系列产品的抽象,可以是抽象类或者是接口。
- 继承这个抽象类,或者实现这个接口的普通类。
- 工厂的抽象,通常是接口,因为只定义方法。
- 工厂的实现,不同的工厂创建不同的实现了抽象类或者接口的产品。
设计思路
除了有简单工厂的优点,解决了简单工厂违背开闭原则这点。比较容易拓展新的产品,只需要新增个工厂实现抽象,实现具体的创建逻辑即可。通过工厂类的子类实现来决定创建哪个对象。
适用于应用层(调用方),不依赖于产品类实例如何被创建、实现等细节的情景。
优缺点
优点:用户只需要关心产品对应的工厂,无须关心实现细节。加入新产品符合开闭原则,提高了拓展性。
缺点:类会变多,因为一个产品对应一个工厂,增加了代码的复杂度。
示意图
抽象工厂模式
提供一个创建一系列相关或互相依赖对象的接口,无须指定他们具体的类。
抽象工厂需要的元素
- 多个系列产品的抽象,可以是接口或者抽象类。
- 继承这些抽象类,或者实现这些接口的具体产品。
- 抽象的工厂或者是接口,定义了创建某个产品族产品的一些方法。
- 工厂的实现类,实现了创建某个产品族产品的一些方法。
设计思路
工厂方法模式,一个工厂创建一个产品,问题在什么?问题在于随着需要的产品越来越多,代码会变得越来越臃肿。抽象工厂复杂的点在于,需要抽象出产品的共性,定义同一个系列的产品。
适用于有一系列相关的产品对象,可以抽象为同一产品族的情景下。提供一个产品类的库,所有的产品以同样的接口实现,从而调用方不依赖具体实现。
优缺点
优点:将一个系列的产品一起创建,当产品越来越多,如果做好了产品的抽象和分类,代码不会像简单工厂那么臃肿。 缺点:规定了所有的可能被创建的产品的集合,产品族中拓展新的产品困难,需要修改抽象工厂的接口(但是拓展另一个产品族就不需要修改抽象工厂的接口,只要增加新的工厂就可以)。
示意图
总结
简单工厂到工厂方法模式再到抽象工厂,其实是为了解决屏蔽掉调用方,构造对象的复杂逻辑,然后随着系统复杂度不断上升,而做出的选择。简单工厂的问题在于不符合开闭原则,一个工厂也只能生产一类产品(其实可以定义一个工厂,多个方法,返回不同的接口,但我觉得这不符合单一职责,并且会显的很奇怪,比如一个日历工厂,生产日志对象,很显然不合理)。解决这个问题,就用到了工厂方法模式。但是工厂模式虽然解决了开闭原则,易于拓展了,但是一个工厂创建一个类,随着类的增加,代码会变得很臃肿,那么很容易想到,根据产品族,产品等级,是不是可以让一个工厂不止生产一个产品呢?是的,根据产品族,让一个工厂可以有生产出一系列的产品的能力。当然这又会带来新的问题,一个是系统复杂度上升,比较难以理解,另外就是如果引入产品族,那么修改的时候,又会违背开闭原则。
其实,这些原则是参考,尽量遵守。但是以业务为主,如果需要修改了,违背开闭原则修改代码并不是不对的,代码本身也是迭代开发的,应该没什么代码一出生到死都不变的。
在这里也思考一下,设计模式是为了什么,是为了解决系统复杂度上升,对于代码关系逻辑之间的一种组织。也是为了,当开发团队很庞大,每个人不能了解到全貌,必须要有合适的设计模式,来从代码的层面,实现更好的分工合作(解耦)。比如工厂模式,调用方就只要关心哪个工厂,哪个方法可以拿到需要的东西,而不需要关心这个东西生成的过程是否是非常复杂的了。