抽象工厂模式是工厂方法模式的升级版本,主要是引入了一个产品族的概念,将针对单一产品升级到了针对多个产品品种和产品分类。java
原文连接:git
http://tianweili.github.io/blog/2015/03/11/abstract-factory-pattern/github
抽象工厂模式定义:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.为建立一组相关或相互依赖的对象提供一个接口,并且无需指定他们具体的类。ide
抽象工厂模式是工厂方法模式的升级版本,主要是引入了一个产品族的概念,将针对单一产品升级到了针对多个产品品种和产品分类。网站
{% img /design-pattern/abstract-factory-uml.png %}操作系统
左边的UML图并不复杂,主要包括2个抽象产品和一个抽象工厂。两个具体实现工厂各对应建立两个不一样类别产品。code
抽象工厂模式关键点在于有了多个产品族。对象
如上图所示,ProductA1和ProductA2就是属于一个产品族。ProductA1和ProductB1分别属于两个不一样的产品族。上面的UML图中有两个产品族。blog
有几个抽象产品类就有几个产品族。继承
有几个产品族,在工厂中就有几个建立方法。
继承于同一个抽象产品类的属于不一样的产品等级。
ProductA1和ProductA2就是两个产品等级。ProductA1和ProductB1属于同一个产品等级。
有几个产品等级,就有几个实现工厂类。
在每一个工厂类中,实现了不一样产品族的建立方法。
public interface AbstractProductA { public void method(); } public class ProductA1 implements AbstractProductA{ public void method() { System.out.println("This is ProductA1."); } } public class ProductA2 implements AbstractProductA{ public void method() { System.out.println("This is ProductA2."); } } public interface AbstractProductB { public void method(); } public class ProductB1 implements AbstractProductB{ public void method() { System.out.println("This is ProductB1."); } } public class ProductB2 implements AbstractProductB{ public void method() { System.out.println("This is ProductB2."); } } public interface AbstractFactory { public AbstractProductA createProductA(); public AbstractProductB createProductB(); } public class Factory1 implements AbstractFactory{ public AbstractProductA createProductA() { return new ProductA1(); } public AbstractProductB createProductB() { return new ProductB1(); } } public class Factory2 implements AbstractFactory{ public AbstractProductA createProductA() { return new ProductA2(); } public AbstractProductB createProductB() { return new ProductB2(); } }
客户端调用
public class Client { public static void main(String[] args) { AbstractFactory factory1 = new Factory1(); AbstractFactory factory2 = new Factory2(); AbstractProductA productA1 = factory1.createProductA(); AbstractProductB productB1 = factory1.createProductB(); AbstractProductA productA2 = factory2.createProductA(); AbstractProductB productB2 = factory2.createProductB(); } }
在上面的客户端调用代码中,没有与具体的产品实现类有关的代码。因此在须要某个具体产品的时候,只须要知道与之对应的工厂来生产就能够了。
抽象工厂模式与工厂方法模式的关键不一样在于引入了一个产品族的概念,工厂方法模式至关于只有一个产品族,而抽象工厂模式有多个产品族。
在有多个产品族的时候只能使用抽象工厂模式了。
针对多个产品族,每一个实现工厂都有相应的建立对应产品的方法。而工厂方法模式中实现工厂中只会有一个建立产品的方法。
高层模块只须要知道生产相应产品的工厂类是谁,就能由工厂建立相应的产品对象。而他不用关心具体产品生产过程,符合迪米特法则。只依赖抽象产品,符合依赖倒置原则。使用产品子类替换产品父类,符合里氏替换原则。
不一样产品族之间的约束放在工厂类中来实现,不对外公开,封装性好。
想较于工厂方法模式,能够应付产品更为复杂的场合。
在产品等级结构层面上符合开闭原则,增长一个产品等级结构扩展性好。
在产品族层面上不符合开闭原则,增长一个产品族,即至关于增长一个抽象产品时,须要修改大量的其余实现工厂,在产品族层面上扩展性很差。
当涉及到多个产品族的时候,就须要使用抽象工厂模式了。
听说抽象工厂模式最初应用于多个操做系统软件开发上,好比要开发一个系统桌面软件,要应用到Windows和Linux操做系统上。那么对于这样的状况咱们是否是要分别为两种操做系统开发不一样的软件呢?固然不是。对于开发一个桌面软件来讲分为界面UI和功能代码等,那么就能够应用抽象工厂模式了,界面UI和功能代码都分别为Windows和Linux开发不一样的一套,而后利用工厂在须要Windows的时候调用建立相应的Windows的界面UI和功能代码。
作过一个爬虫工程,需求是这样的,公司有多个站点,想要去根据搜索关键字获取它们在搜索页面一些要素,好比广告、文章、产品等信息。那么针对这种需求就采用了抽象工厂模式。首先将广告、文章等分别都做为一个产品族,每一个网站都是一个产品等级。这样抽象出来的解析广告类、解析文章类等抽象接口,由每一个具体产品去实现某个站点的解析广告,另外一个产品族的具体产品去实现解析文章类,将具体解析过程封装在了产品内部。再使用相应的工厂来建立一个个产品族内的产品。
关键逻辑删减版类图以下
{% img /design-pattern/sitecrawler-uml.png %}
这样就实现了良好的封装性,高层模块想调用知道某个网站的一些统计分析数据时,只须要知道相应的工厂来生产就好了,不须要知道具体的实现过程和复杂的处理逻辑。在产品等级也就是网站层面上扩展性好,后来有新增站点的时候,直接增长产品等级,实现相应的抽象产品类,再增长一个具体实现工厂就行了。
不过它的缺点是在产品族也就是想新增解析需求的时候扩展性很差,好比后来想增长对搜索关键词后的首页文章内容进行统计,以便查看匹配度时。就须要增长一个产品族即抽象产品模块,须要修改每一个工厂的代码。
做者:李天炜
原文连接:http://tianweili.github.io/blog/2015/03/11/abstract-factory-pattern/
转载请注明做者和文章出处,谢谢。