【原】从头学习设计模式(四)——抽象工厂模式
一 、引入
前面我们讨论了“简单工厂模式”和“工厂方法模式”,这次我们来学习设计模式中最后的一种工厂模式——抽象工厂模式。
抽象工厂模式其实是工厂方法模式的一种扩展,应用抽象工厂模式可以创建一系列的产品(产品族),而不是像工厂方法模式中的只能创建一种产品。先我们来看一下抽象工厂模式的标准定义:
抽象工厂模式定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
官方的定义一般都不易理解,我们就来模拟一个场景来说明一下这其中的关系吧。
富士康公司给两个品牌作代工产品:苹果和三星。众所周知,这两个品牌都有手机和平板产品,由于生产工艺的不同,富士康开设了两条生产线,一条线只生产手机,另一条线只生产平板,总负责人是车间主任老王。一个卖苹果设备的采购商找到老王,说先给我来1台苹果的iPad, 老王转身到生产平板的生产线上的操作台,往电脑里输入“苹果牌”三个字,很快1台iPad生产出来了。采购商又说,再给我来1台苹果的iPhone吧,老王又转身到手机的生产线,在电脑里输入“苹果牌”,很快一台iPhone又造好了。
看出来了吗?这里有两种抽象的产品(苹果产品和三星产品),而每种抽象的产品都有两种产品角色(手机和平板电脑),这样就要建立两种工厂(手机工厂和平板工厂)分别负责不同产品角色的实例化。 老王就是工厂的总接口,他负责帮你找到正确的生产工厂,并且拿到你想要的那一种类型的产品。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式针对的是多个产品等级结构。有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。总结一下我认为可以应用到抽象工厂模式的实际例子:
1. 两种产品:PC和MAC,两种产品等级:RAM,CPU
2. 两种产品:水果和蔬菜,两种产品等级:南方特产,北方特产
3. 两种产品:男人和女人,三种产品等级:黄种人,黑人,白人
就类似这种结构的对象关系都可以用抽象工厂模式来构造。。。。。
二、类图
下面是从百度百科里引用的类图。
三、代码会说话
用简单的代码来说明
1 /// <summary> 2 /// 苹果产品系列 3 /// </summary> 4 public interface Apple 5 { 6 void AppleStyle(); 7 } 8 9 /// <summary> 10 /// 三星产品系列 11 /// </summary> 12 public interface Sumsung 13 { 14 void BangziStyle(); 15 } 16 17 public class iphone : Apple 18 { 19 public void AppleStyle() 20 { 21 Console.WriteLine("Apple's style: iPhone!"); 22 } 23 } 24 25 public class ipad : Apple 26 { 27 28 public void AppleStyle() 29 { 30 Console.WriteLine("Apple's style: iPad!"); 31 } 32 33 } 34 35 public class note2 : Sumsung 36 { 37 public void BangziStyle() 38 { 39 Console.WriteLine("Bangzi's style : Note2!"); 40 } 41 42 } 43 44 public class Tabs : Sumsung 45 { 46 public void BangziStyle() 47 { 48 Console.WriteLine("Bangzi's style : Tab!"); 49 } 50 } 51 52 public interface Factory 53 { 54 Apple createAppleProduct(); 55 Sumsung createSumsungProduct(); 56 } 57 58 /// <summary> 59 /// 手机工厂 60 /// </summary> 61 public class Factory_Phone : Factory 62 { 63 public Apple createAppleProduct() 64 { 65 return new iphone(); 66 } 67 68 public Sumsung createSumsungProduct() 69 { 70 return new note2(); 71 } 72 } 73 74 /// <summary> 75 /// 平板工厂 76 /// </summary> 77 public class Factory_Pad : Factory 78 { 79 public Apple createAppleProduct() 80 { 81 return new ipad(); 82 } 83 84 public Sumsung createSumsungProduct() 85 { 86 return new Tabs(); 87 } 88 }
模拟调用过程。
1 public static void Main(string[] args) 2 { 3 //采购商要一台iPad和一台Tab 4 Factory factory = new Factory_Pad(); 5 Apple apple = factory.createAppleProduct(); 6 apple.AppleStyle(); 7 Sumsung sumsung = factory.createSumsungProduct(); 8 sumsung.BangziStyle(); 9 10 //采购商又要一台iPhone和一台Note2 11 factory = new Factory_Phone(); 12 apple = factory.createAppleProduct(); 13 apple.AppleStyle(); 14 sumsung = factory.createSumsungProduct(); 15 sumsung.BangziStyle(); 16 17 Console.ReadKey(); 18 }
运行结果:
四、总结
抽象工厂模式最大的缺点就是对产品族的扩展非常困难,如果要添加一个新的品牌联想的话,看看我们的改动会有多大吧。。。。 首先要在Factory接口中声明新方法
Lenovo createLenovoProduct()
然后在所有现有的工厂实现类中分别实现这个新的createLenovoProduct()方法,如果工厂类有很多,改动的地方也会很多的。。违反了开闭原则,并且作为契约的接口修改了,其他所有和接口有关的代码可能都要改。
反过来想,如果对产品角色扩展难不难呢?比如我要添加一个新的角色“电脑”,改动的地方有多少呢?只需要新建的各品牌电脑产品类和一个电脑工厂而已,都是扩展而不是修改,这样就又符合了开闭原则。所以说,抽象工厂模式对于产品角色的扩展是很容易的。
到本章为止,设计模式中的所有工厂类的模式就都介绍完啦~ 边学边教,难免会有理解错误的地方,请大家帮我指正~