工厂模式已经分析了简单工厂模式和工厂方法模式。并且了解了工厂方法模式去简单工厂模式的延伸,工厂方法模式如果不把工厂类抽象的话,就是简单工厂模式。由前面两个工厂模式可以猜测出抽象工厂模式应该是这两种工厂模式的另外一个变化。先来看一下它的定义。
提供一个创建一系列相关或相互依赖的对象的接口,而无需指定它们具体的类。
先简单介绍一下定义的意思,就是需要创建一个接口,这个接口的作用就是用来创建一个以上的对象的,并且这些对象是相互依赖的,还不需要指定它们具体实现的类,应该是别创建对象的类。为了更好的理解,就用急速PDF阅读器切换皮肤为例子来介绍一下。
切换皮肤有多个地方是同时变动风格的。为了例子的简洁易懂,就那下面那个地方为例
- 背景
- 软件头部
很容易看出来,皮肤修改这二个是相互关联的,相互依赖的。不然出来的效果就是似是而非了。
代码示例
给出切换皮肤需要配置的三个部分的类
//系统背景接口(产品A) public interface SystemBackground { public String controlStyle(); } //系统头部(产品B) public interface SystemHead { public String controlStyleB(); } //系统简洁大气背景风格 (产品A1) public class SystemBackgroundImplA implements SystemBackground { @Override public String controlStyle() { // TODO Auto-generated method stub return "简洁大气的背景风格"; } } //系统中国风背景(产品A2) public class SystemBackgoundImplB implements SystemBackground{ @Override public String controlStyle() { // TODO Auto-generated method stub return "中国风的背景风格"; } } //系统简洁大气头部(产品B1) public class SystemHeadImplA implements SystemHead { @Override public String controlStyleB() { // TODO Auto-generated method stub return "简洁大气的系统头部"; } } //系统中国风头部(产品B2) public class SystemHeadImplB implements SystemHead { @Override public String controlStyleB() { // TODO Auto-generated method stub return "中国风的系统头部"; } }
工厂类
//工厂接口 public interface SkinFactory { public void createBackgroundSkin(); public void createHeadSkin(); } //简洁大气皮肤工厂类 public class SkinFactoryJjdq implements SkinFactory { @Override public void createBackgroundSkin() { // TODO Auto-generated method stub SystemBackground sbg = new SystemBackgroundImplA(); System.out.println("切换了"+sbg.controlStyle()); } @Override public void createHeadSkin() { // TODO Auto-generated method stub SystemHead sh = new SystemHeadImplA(); System.out.println("切换了"+sh.controlStyleB()); } } //中国风皮肤工厂类 public class SkinFactoryZgf implements SkinFactory { @Override public void createBackgroundSkin() { SystemBackground sbg = new SystemBackgoundImplB(); System.out.println("切换了"+sbg.controlStyle()); } @Override public void createHeadSkin() { // TODO Auto-generated method stub SystemHead sh = new SystemHeadImplB(); System.out.println("切换了"+sh.controlStyleB()); } }
客户端调用
public class Client { public static void main(String[] args) { SkinFactory sf = new SkinFactoryJjdq(); //简洁大气 System.out.println("--------开始切换【简洁大气】皮肤-----------"); sf.createHeadSkin(); sf.createBackgroundSkin(); System.out.println("*******切换【简洁大气】皮肤结束"); //中国风 System.out.println("\n --------开始切换【中国风】皮肤-----------"); sf = new SkinFactoryZgf(); sf.createHeadSkin(); sf.createBackgroundSkin(); System.out.println("++++++++切换【中国风】皮肤结束"); } }
分析此设计模式
这个例子就是抽象工厂模式的所要解决的问题。把这个例子结构展示出来,可以更好的理解抽象工厂。
通过结构图看出来,工厂类有两个方法来创建产品类,并且这两个方法创建的对象是相互关联的。抽象工厂模式重点就在创建相互关联的对象。还拿例子来说,可以看出来工厂类有两个工厂方法。就是创建两个对象。但是不是随意创建的。他们是相互关联的,如果工厂类中一个创建的是简洁大气的头部皮肤,另外一个是中国风的背景。那出来的皮肤肯定就不是一个成功的产品了。所以他们一定是相互关联的。如果理解了工厂方法模式,那么对于抽象工厂模式来说,只要理解创建相互关联的对象这部分。就基本理解了抽象工厂模式要解决问题的本质。
如果产品族横向扩展(对于这个例子增加新的皮肤),那么添加新的具体工厂实现工厂就扣即可;纵向扩展(对于本例子来说,就是修改皮肤不仅是系统头部和背景,还有另外的依赖部分,比如滑动杆样式),这就需要修改工厂类了。
适应场景
- 一个产品要独立于它的创建组合和表示时。
- 一个系统需要由多个产品系列中的一个来配置时,并且是由多个相互依赖的部分组合成一个产品的。
- 当你提供一个产品类库,只是想显示它们的接口而不是实现时。
三个工厂模式的区别
三个工厂模式是相互关联的,简单工厂是工厂模式中的最简单的一些表达。他的任务就是把需要创建的对象和调用地方解耦。简单工厂类充当桥梁作用,没有考虑其他更多的问题。但是他有弊端,就是不能灵活扩展,只要想扩展,就需要修改工厂类。
为了解决这个问题,就发展了工厂方法模式。把工厂类用抽象类表示,实现具体的产品就用继承抽象工厂类的具体工厂来负责,这样就解决了简单工厂里面的扩展问题。
业务场景纷繁复杂,需要创建的对象也可能是复杂的,为了完成一定功能,需要创建相互关联的多个类。于是,在工厂方法模式基础上,让工厂类实现多个工厂方法。他们创建的对象相互关联共同完成特定功能。这就变成了抽象工厂模式。
小结
至此,工厂模式系统已经介绍完毕,他们都属于创建者模式。简单工厂模式和工厂方法模式使用的场景基本没有什么区别,只是当业务复杂,考虑扩展时候。就舍弃简单工厂而选用工厂方法模式。个人认为很系统应该也是重构发展的。一个场景可能开始用的简单工厂模式,但是随着系统不断发展,为了更灵活扩展,就修改成工厂方法模式。抽象工厂类使用场景看似很清晰,使用也是在系统不断扩展使用场景渐渐清晰的。工厂模式到这里了,如果以后发现没有理解到部分,再进行补充进来