设计模式(0)简单工厂模式html
设计模式(2)工厂方法模式(Factory Method)github
源码地址编程
抽象工厂模式通常的书面定义为:提供一个建立一系列相关或相互依赖对象的接口,而无需指定他们具体的类设计模式
提供建立接口,无需指定具体实现类,这个原则在简单工厂模式和工厂方法模式篇已经反复讲到了,这是面向接口编程的一个基本准则,很显然,从抽象工厂模式的通常定义中能够看出这也是抽象工厂模式的一个核心,而抽象工厂模式的另外一个核心是要解决一系列相关或相依赖对象(产品族)建立的问题。这也是这几种工厂模式的细节区别所在的关键点所在,初学设计模式时每每由于没有认识到这一点区别而对几种工厂模式难以理解ide
咱们能够简单的这么理解,抽象工厂模式不仅仅要解决对象的建立问题,还要涉及到建立的对象之间的相互依赖或者约束关系。工厂方法模式和简单工厂模式解决了单个产品对象建立的问题,它们只关心单个产品对象的建立,而抽象工厂模式是关注的产品族(多个相互关联对象)的建立,最终建立的产品族造成一个新的产品对象。spa
抽象工厂模式的结构图以下:设计
AbstractFactory:抽象工厂类,定义建立某个产品所需相关对象的操做接口3d
ProductFactory1/ProductFactory2:具体的工厂类,实现抽象工厂定义的方法,负责某个产品所需全部对象建立操做接口的具体实现。code
AbstractProductA/AbstractProductB:定义某一类产品对象的接口
ProductA1/ProductA2/ProductB1/ProductB2:具体产品对象的实现
若是对上面的文字描述还不能有一个直观的认识,咱们仍然从一个简单的应用场景来讲明抽象工厂模式的引入时机。
野外商店老板为了更好的服务众英雄,特将店内隐身药水进行了一次升级,分为红瓶装(瓶口直径2cm)、蓝瓶装(瓶口直径5cm)2款,而且2种瓶子分别搭配圆形(2cm)和方形(5cm)两种款式的瓶盖。英雄们来到商店后,只须要将本身的的须要告诉商店老板,老板根据英雄的要求,去取瓶子和盖子进行组装便可。
在应用抽象工厂模式以前,咱们很简单的使用简单工厂模式实现这个需求。
定义瓶子接口及实现类
/// <summary> /// 定义瓶子接口 /// </summary> public interface IBottle { /// <summary> /// 展现本身的信息 /// </summary> void ShowInfo(); }
/// <summary> /// 红色瓶子 /// </summary> public class RedBottle : IBottle { /// <summary> /// 展现本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一个热情火辣的红色瓶子,个人瓶口直径是2cm。"); } }
定义瓶盖接口及实现类
/// <summary> /// 定义瓶盖接口 /// </summary> public interface ICap { /// <summary> /// 展现本身的信息 /// </summary> void ShowInfo(); }
/// <summary> /// 圆形瓶盖 /// </summary> public class RoundCap : ICap { /// <summary> /// 展现本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一个圆形瓶盖,个人直径是2cm。"); } }
/// <summary> /// 方形瓶子 /// </summary> public class SquareCap : ICap { /// <summary> /// 展现本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一个方形瓶盖,个人直径是5cm。"); } }
定义建立瓶子和瓶盖的简单工厂
/// <summary> /// 瓶子建立工厂方法 /// </summary> public class BottleFactory { /// <summary> /// 建立瓶子对象 /// </summary> /// <param name="color">瓶子颜色</param> /// <returns></returns> public static IBottle CreateBottle(string color) { if (color == "red") return new RedBottle(); if (color == "blue") return new BlueBottle(); return null; } }
/// <summary> /// 瓶盖建立工厂方法 /// </summary> public class CapFactory { /// <summary> /// 建立瓶子对象 /// </summary> /// <param name="shape">瓶盖形状</param> /// <returns></returns> public static ICap CreateCap(string shape) { if (shape == "round") return new RoundCap(); if (shape == "square") return new SquareCap(); return null; } }
最终成品组装类定义
/// <summary> /// 隐形药水组装者 /// </summary> public class ProductMaker { private IBottle _bottle; // 瓶子对象 private ICap _cap; // 瓶盖对象 /// <summary> /// 建立最终药水对象 /// </summary> /// <param name="bottleColor"></param> /// <param name="capShape"></param> public void MakeProduct(string bottleColor, string capShape) { _bottle = BottleFactory.CreateBottle(bottleColor); _cap = CapFactory.CreateCap(capShape); Console.WriteLine("准备英雄须要的瓶子和瓶盖。"); _bottle.ShowInfo(); _cap.ShowInfo(); Console.WriteLine("开始往瓶子了灌入隐形药水,而后封上瓶盖。"); } }
客户端调用
static void Main(string[] args) { ProductMaker pm = new ProductMaker(); pm.MakeProduct("red", "round"); // 提供给英雄红瓶子圆盖子的隐形药水 Console.WriteLine(); pm.MakeProduct("blue", "square"); // 提供给英雄蓝瓶子方盖子的隐形药水 Console.ReadLine(); }
这样,咱们经过接口进行隔离,解决了不一样瓶子,不一样盖子建立时,客户端无需关心具体建立过程,只须要告诉工厂须要何种类型的对象便可。但同时会暴露一个很明显的问题就是,咱们建立的瓶子和瓶盖2个对象并非孤立存在的,2个对象之间是有明显的相互关系的,那就是平口尺寸必须和瓶盖尺寸保持一直,不然就会让店老板出现灌装好药水却拧不上盖子的尴尬。此时应该会对上面提到的抽象工厂的定义有进一步的理解,也在这种场景下,是咱们必需要引入抽象工厂模式的时候了。
0、提炼抽象工厂类
根据抽象工厂方法的结构图,咱们首先定义个一个抽象工厂类,该抽象工厂定义瓶子和瓶盖2个对象的建立接口。
/// <summary> /// 抽象工厂类 /// </summary> public abstract class AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public abstract IBottle CreateBottle(); /// <summary> /// 建立瓶盖 /// </summary> /// <returns></returns> public abstract ICap CreateCap(); }
一、抽象工厂的具体实现
分析产品的组合状况,实际上只存在2种类型的最终产品,红瓶子圆盖子和蓝瓶子方盖子,咱们分别定义2个抽象工厂的具体实现类
/// <summary> /// 红瓶子圆盖子工厂类 /// </summary> public class RedBottleAndRoundCapFactory : AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public override IBottle CreateBottle() { return BottleFactory.CreateBottle("red"); } /// <summary> /// 建立瓶盖 /// </summary> /// <returns></returns> public override ICap CreateCap() { return CapFactory.CreateCap("round"); } }
/// <summary> /// 蓝瓶子方盖子工厂类 /// </summary> public class BlueBottleAndSquareCapFactory : AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public override IBottle CreateBottle() { return BottleFactory.CreateBottle("blue"); } /// <summary> /// 建立瓶盖 /// </summary> /// <returns></returns> public override ICap CreateCap() { return CapFactory.CreateCap("square"); } }
二、最终产品组装类的修改实现
跟原来的实现相比较,最终产品组装类不在从客户端传入瓶子、瓶盖的参数经过对应的工厂方法建立,而是直接传入已经定义好的瓶子瓶盖组装工厂类对象,可以作到瓶子瓶盖必须配套建立。
/// <summary> /// 建立最终药水对象 /// </summary> /// <param name="factory">抽象工厂具体对象</param> public void MakeProduct(AbstractFactory factory) { _bottle = factory.CreateBottle(); _cap = factory.CreateCap(); Console.WriteLine("准备英雄须要的瓶子和瓶盖。"); _bottle.ShowInfo(); _cap.ShowInfo(); Console.WriteLine("开始往瓶子了灌入隐形药水,而后封上瓶盖。"); }
三、客户端调用
ProductMaker pm = new ProductMaker(); AbstractFactory factory = new RedBottleAndRoundCapFactory(); // 提供给英雄红瓶子圆盖子的隐形药水 pm.MakeProduct(factory); Console.WriteLine(); factory = new BlueBottleAndSquareCapFactory(); // 提供给英雄蓝瓶子方盖子的隐形药水 pm.MakeProduct(factory); Console.ReadLine();
经过建立的多个对象之间的关联关系阐述了抽象工厂模式与其余工厂模式的区别以及使用时机。基于上面的示例,咱们能够总结出抽象工厂模式的具备如下优势:
0、分离接口和实现
客户端使用抽象工厂方法来建立须要的对象,只须要传入抽象方法的,无需关注内部具体实现逻辑,实现接口与具体实现的分离解耦。
一、易于产品族切换
一个具体抽象工厂的实现其实就是表明一个产品族,客户端经过参数选用不一样的工厂实现,就能够在不一样的产品建立中进行切换。
抽象工厂模式的缺点也显而易见,那就是扩展新产品的过程会比较麻烦,好比一个产品族中包含的产品发生了变化,好比增长或减小部件,就须要修改抽象工厂,同时须要修改全部的抽象工厂实现类。