抽象工厂模式是工厂方法模式的升级版本,主要是引入了一个产品族的概念,将针对单一产品升级到了针对多个产品品种和产品分类。
原文链接:
http://tianweili.github.io/blog/2015/03/11/abstract-factory-pattern/
介绍
抽象工厂模式定义:
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们具体的类。
抽象工厂模式是工厂方法模式的升级版本,主要是引入了一个产品族的概念,将针对单一产品升级到了针对多个产品品种和产品分类。
UML类图
左边的UML图并不复杂,主要包括2个抽象产品和一个抽象工厂。两个具体实现工厂各对应创建两个不同类别产品。
产品族和产品等级
抽象工厂模式关键点在于有了多个产品族。
如上图所示,ProductA1和ProductA2就是属于一个产品族。ProductA1和ProductB1分别属于两个不同的产品族。上面的UML图中有两个产品族。
有几个抽象产品类就有几个产品族。
有几个产品族,在工厂中就有几个创建方法。
继承于同一个抽象产品类的属于不同的产品等级。
ProductA1和ProductA2就是两个产品等级。ProductA1和ProductB1属于同一个产品等级。
有几个产品等级,就有几个实现工厂类。
在每个工厂类中,实现了不同产品族的创建方法。
代码示例
|
|
客户端调用
|
|
在上面的客户端调用代码中,没有与具体的产品实现类有关的代码。所以在需要某个具体产品的时候,只需要知道与之对应的工厂来生产就可以了。
与工厂方法模式的区别
抽象工厂模式与工厂方法模式的关键不同在于引入了一个产品族的概念,工厂方法模式相当于只有一个产品族,而抽象工厂模式有多个产品族。
在有多个产品族的时候只能使用抽象工厂模式了。
针对多个产品族,每个实现工厂都有相应的创建对应产品的方法。而工厂方法模式中实现工厂中只会有一个创建产品的方法。
优点
高层模块只需要知道生产相应产品的工厂类是谁,就能由工厂创建相应的产品对象。而他不用关心具体产品生产过程,符合迪米特法则。只依赖抽象产品,符合依赖倒置原则。使用产品子类替换产品父类,符合里氏替换原则。
不同产品族之间的约束放在工厂类中来实现,不对外公开,封装性好。
想较于工厂方法模式,可以应付产品更为复杂的场合。
在产品等级结构层面上符合开闭原则,增加一个产品等级结构扩展性好。
缺点
在产品族层面上不符合开闭原则,增加一个产品族,即相当于增加一个抽象产品时,需要修改大量的其他实现工厂,在产品族层面上扩展性不好。
适用场景
当涉及到多个产品族的时候,就需要使用抽象工厂模式了。
应用实例
开发软件应用多个操作系统
据说抽象工厂模式最初应用于多个操作系统软件开发上,比如要开发一个系统桌面软件,要应用到Windows和Linux操作系统上。那么对于这样的情况我们是不是要分别为两种操作系统开发不同的软件呢?当然不是。对于开发一个桌面软件来说分为界面UI和功能代码等,那么就可以应用抽象工厂模式了,界面UI和功能代码都分别为Windows和Linux开发不同的一套,然后利用工厂在需要Windows的时候调用创建相应的Windows的界面UI和功能代码。
不同网站爬虫解析
做过一个爬虫工程,需求是这样的,公司有多个站点,想要去根据搜索关键字获取它们在搜索页面一些要素,比如广告、文章、产品等信息。那么针对这种需求就采用了抽象工厂模式。首先将广告、文章等分别都作为一个产品族,每个网站都是一个产品等级。这样抽象出来的解析广告类、解析文章类等抽象接口,由每个具体产品去实现某个站点的解析广告,另一个产品族的具体产品去实现解析文章类,将具体解析过程封装在了产品内部。再使用相应的工厂来创建一个个产品族内的产品。
关键逻辑删减版类图如下
这样就实现了良好的封装性,高层模块想调用知道某个网站的一些统计分析数据时,只需要知道相应的工厂来生产就行了,不需要知道具体的实现过程和复杂的处理逻辑。在产品等级也就是网站层面上扩展性好,后来有新增站点的时候,直接增加产品等级,实现相应的抽象产品类,再增加一个具体实现工厂就好了。
不过它的缺点是在产品族也就是想新增解析需求的时候扩展性不好,比如后来想增加对搜索关键词后的首页文章内容进行统计,以便查看匹配度时。就需要增加一个产品族即抽象产品模块,需要修改每个工厂的代码。
作者:李天炜
原文链接:http://tianweili.github.io/blog/2015/03/11/abstract-factory-pattern/
转载请注明作者和文章出处,谢谢。