设计模式—抽象工厂模式
前言:
工厂方法模式是为了克服简单工厂模式的确定而设计的,简单工厂模式的工厂类会随着产品类的增加而增加额外的代码(case),而工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的扩展性;但是现实生活中,一个工厂只生成一种产品显然是不可能的,如果使用工厂方法模式那么我们的代码中就会出现很多的工厂类,很多的实例,显然这是我们不想要的。那么抽象工厂就出现了
抽象工厂介绍:
1)实际例子
首先用生活中的例子‘绝味’在代码层中去实现。例如:绝味鸭脖想在江西南昌和上海开分店,但是由于当地人的口味不一样,在南昌的所有绝味的东西会做的辣一点,而上海不喜欢吃辣的,所以上海的所有绝味的东西都 不会做的像南昌的那样辣,然而这点不同导致南昌绝味工厂和上海的绝味工厂生成所有绝味的产品都不同,也就是某个具体工厂需要负责一系列产品(指的是绝味所 有食物)的创建工作,下面就具体看看如何使用抽象工厂模式来实现这种情况。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 #region 产品集 9 /// <summary> 10 /// 鸭脖抽象类,供每个地方的鸭脖类继承 11 /// </summary> 12 public abstract class YaBo 13 { 14 public abstract void Print(); 15 } 16 /// <summary> 17 /// 鸭架抽象类,供每个地方的鸭架类继承 18 /// </summary> 19 public abstract class YaJia 20 { 21 public abstract void Print(); 22 } 23 24 /// <summary> 25 /// 南昌的鸭脖类,因为江西人喜欢吃辣的,所以南昌的鸭脖稍微会比上海做的辣 26 /// </summary> 27 public class NanChangYaBo : YaBo 28 { 29 public override void Print() 30 { 31 Console.WriteLine("南昌鸭脖"); 32 } 33 } 34 /// <summary> 35 /// 上海的鸭脖没有南昌的鸭脖做的辣 36 /// </summary> 37 public class ShangHaiYaBo : YaBo 38 { 39 public override void Print() 40 { 41 Console.WriteLine("上海鸭脖"); 42 } 43 } 44 /// <summary> 45 /// 南昌的鸭架 46 /// </summary> 47 public class NanChangYaJia : YaJia 48 { 49 public override void Print() 50 { 51 Console.WriteLine("南昌鸭架"); 52 } 53 } 54 /// <summary> 55 /// 上海的鸭架 56 /// </summary> 57 public class ShangHaiYaJia : YaJia 58 { 59 public override void Print() 60 { 61 Console.WriteLine("上海鸭架"); 62 } 63 } 64 #endregion 65 66 #region 工厂集 67 /// <summary> 68 /// 抽象工厂类,提供创建两个不同地方的鸭架和鸭脖的接口 69 /// </summary> 70 public abstract class AbstractFactory 71 { 72 // 抽象工厂提供创建一系列产品的接口,这里作为例子,只给出了绝味中鸭脖和鸭架的创建接口 73 public abstract YaBo CreateYaBo(); 74 public abstract YaJia CreateYaJia(); 75 } 76 77 /// <summary> 78 /// 南昌绝味工厂负责制作南昌的鸭脖和鸭架 79 /// </summary> 80 public class NanChangFactory : AbstractFactory 81 { 82 // 制作南昌鸭脖 83 public override YaBo CreateYaBo() 84 { 85 return new NanChangYaBo(); 86 } 87 // 制作南昌鸭架 88 public override YaJia CreateYaJia() 89 { 90 return new NanChangYaJia(); 91 } 92 } 93 /// <summary> 94 /// 上海绝味工厂负责制作上海的鸭脖和鸭架 95 /// </summary> 96 public class ShangHaiFactory : AbstractFactory 97 { 98 // 制作上海鸭脖 99 public override YaBo CreateYaBo() 100 { 101 return new ShangHaiYaBo(); 102 } 103 // 制作上海鸭架 104 public override YaJia CreateYaJia() 105 { 106 return new ShangHaiYaJia(); 107 } 108 } 109 #endregion 110 }
调用方式:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 class Program 9 { 10 /// <summary> 11 /// 下面以绝味鸭脖连锁店为例子演示下抽象工厂模式 12 /// 因为每个地方的喜欢的口味不一样,有些地方喜欢辣点的,有些地方喜欢吃不辣点 13 /// 客户端调用 14 /// </summary> 15 /// <param name="args"></param> 16 static void Main(string[] args) 17 { 18 // 南昌工厂制作南昌的鸭脖和鸭架 19 AbstractFactory nanchangFactory = new NanChangFactory(); 20 nanchangFactory.CreateYaBo().Print(); 21 nanchangFactory.CreateYaJia().Print(); 22 23 // 上海工厂制作上海的鸭脖和鸭架 24 AbstractFactory shanghaiFactory = new ShangHaiFactory(); 25 shanghaiFactory.CreateYaBo().Print(); 26 shanghaiFactory.CreateYaJia().Print(); 27 } 28 } 29 }
2)抽象工厂模式:提供一个创建产品的接口来负责创建相关或依赖的对象,而不明确指定具体类
抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道实际生产出来的具体产品是什么,这样客户就可以从具体产品中被解耦
3)需求变更
如果要在湖南开一家分店,那就是麻辣味的了,抽象工厂模块可能轻松的对代码进行扩展
1 /// <summary> 2 /// 如果绝味又想开一家湖南的分店时,因为湖南喜欢吃麻的 3 /// 所以这是有需要有一家湖南的工厂专门制作 4 /// </summary> 5 public class HuNanFactory : AbstractFactory 6 { 7 8 // 制作湖南鸭脖 9 public override YaBo CreateYaBo() 10 { 11 return new HuNanYaBo(); 12 } 13 14 15 // 制作湖南鸭架 16 public override YaJia CreateYaJia() 17 { 18 return new HuNanYajia(); 19 } 20 } 21 22 /// <summary> 23 /// 湖南的鸭脖 24 /// </summary> 25 public class HuNanYaBo : YaBo 26 { 27 public override void Print() 28 { 29 Console.WriteLine("湖南的鸭脖"); 30 } 31 } 32 33 /// <summary> 34 /// 湖南的鸭架 35 /// </summary> 36 public class HuNanYajia : YaJia 37 { 38 public override void Print() 39 { 40 Console.WriteLine("湖南的鸭架子"); 41 } 42 }
4)抽象工厂分析
抽象工厂模式将具体产品的创建延迟到具体工厂子类中,将对象封装起来,可以减少客户端与具体产品之间的依赖,这样有利于后期的维护和扩展,这是抽象工厂的优点。
同时抽象工厂也有不足的地方,如下:
很难支持新种类产品的变化,因为抽象工厂接口中已经确定了可以被创建的产品集合,如果要添加新产品必须要修改抽象工厂的接口,而且涉及到抽象工厂类以及子类的变化,这样就违背了‘开发-封闭’原则
5)使用抽象工厂场景
一个系统不要求知道产品类如果创建,组合,表达
这个系统有多个系列产品,而系统中只消费其中某一系列产品
要求提供一个产品类的库,所以产品以同样的接口出现,客户端不需要依赖具体实现
6)简单方法工厂和抽象工厂模式区别
其实工厂方法模式是用来创建一个产品的等级结构的,而抽象工厂模式用来创建多个产品的等级结构的。
工厂方法类创建只有一个方法创建一种产品,抽象工厂类一般有多个方法创建多个产品。
工厂方法模式只有一个抽象产品类,抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
简而言之->
工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。