前一章节,我们介绍了简单工厂模式以及工厂方法模式,但是这两种模式都存在一定的局限性,只能生产某一类型下的某一种产品,如果需求变更,同类型下出现了不同的产品,比如芝士披萨不仅有口味上的不同,同时存在外观上的不同。这种时候,工厂模式显然不再满足要求,该怎么办呢?于是我们想到DIP原则,它不正是为了解决这种情况而存在的吗?接下来我们来介绍下抽象工厂模式:
1、抽象工厂模式定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
2、抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
3、从设计层面来说,抽象工厂模式就是对简单工厂模式的改进(即进一步抽象化)
4、将工厂抽象成两层,抽象工厂和具体的实现工厂。
还是拿pizza订购举例,我们定义一个抽象工厂AbsFactory,由子类工厂实现该抽象工厂;订购披萨OrderPizza依赖抽象,不依赖具体的实现。
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 new OrderPizza(new BJFactory()); 6 } 7 } 8 9 internal class OrderPizza 10 { 11 private AbsFactory factory; 12 13 public OrderPizza(AbsFactory factory) 14 { 15 setFactory(factory); 16 Order(); 17 } 18 19 private void setFactory(AbsFactory factory) 20 { 21 this.factory = factory; 22 } 23 24 private void Order() 25 { 26 Pizza pizza = null; 27 string orderType = ""; 28 do 29 { 30 Console.Write("请输入订购类型:"); 31 orderType = Console.ReadLine(); 32 pizza = this.factory.createPizza(orderType); 33 if (pizza == null) 34 { 35 Console.WriteLine("订购失败"); 36 break; 37 } 38 //开始制作 39 pizza.prepare(); 40 pizza.bake(); 41 pizza.cut(); 42 pizza.box(); 43 } while (true); 44 } 45 } 46 47 internal interface AbsFactory 48 { 49 Pizza createPizza(string orderType); 50 } 51 52 internal class BJFactory : AbsFactory 53 { 54 public Pizza createPizza(string orderType) 55 { 56 Pizza pizza = null; 57 if (orderType == "cheese") 58 { 59 pizza = new BJCheesePizza(); 60 pizza.setName("北京芝士披萨"); 61 } 62 else if (orderType == "greek") 63 { 64 pizza = new BJGreekPizza(); 65 pizza.setName("北京希腊披萨"); 66 } 67 return pizza; 68 } 69 } 70 71 internal class LDFactory : AbsFactory 72 { 73 public Pizza createPizza(string orderType) 74 { 75 Pizza pizza = null; 76 if (orderType == "cheese") 77 { 78 pizza = new LDCheesePizza(); 79 pizza.setName("伦敦芝士披萨"); 80 } 81 else if (orderType == "greek") 82 { 83 pizza = new LDGreekPizza(); 84 pizza.setName("伦敦希腊披萨"); 85 } 86 return pizza; 87 } 88 } 89 90 internal abstract class Pizza 91 { 92 private string name; 93 94 public abstract void prepare(); 95 96 public void bake() 97 { 98 Console.WriteLine($"{this.name} 烘培"); 99 } 100 101 public void cut() 102 { 103 Console.WriteLine($"{this.name} 修剪"); 104 } 105 106 public void box() 107 { 108 Console.WriteLine($"{this.name} 打包"); 109 } 110 111 public void setName(string name) 112 { 113 this.name = name; 114 } 115 } 116 117 internal class BJCheesePizza : Pizza 118 { 119 public override void prepare() 120 { 121 Console.WriteLine("北京的芝士披萨准备中"); 122 } 123 } 124 125 internal class BJGreekPizza : Pizza 126 { 127 public override void prepare() 128 { 129 Console.WriteLine("北京的希腊披萨准备中"); 130 } 131 } 132 133 internal class LDCheesePizza : Pizza 134 { 135 public override void prepare() 136 { 137 Console.WriteLine("伦敦的芝士披萨准备中"); 138 } 139 } 140 141 internal class LDGreekPizza : Pizza 142 { 143 public override void prepare() 144 { 145 Console.WriteLine("伦敦的希腊披萨准备中"); 146 } 147 }
读过一些博主的博文以及评论,有一些理解还是蛮到位的:
1、抽象工厂比工厂方法复杂的多,它们的目的不同。工厂方法意在延迟加载,而抽象方法意在高内聚低耦合。
2、工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂可以创建多个。
参考:https://www.runoob.com/design-pattern/abstract-factory-pattern.html