1. 意图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
别名 Kit
设计模式一书中这个模式作为创建型模式的第一个模式出现,但是这个模式本身和Singleton(单例), Factory Method(工厂方法) 又有一定的关联性,所以建议可以先看这个模式,在看完单例和工厂方法模式后再回头看一遍抽象工厂会比较好。
重点在于“一系列“这三个字,同时这些对象是”相关或相互依赖的“,作者举了一个多视感标准的用户界面工具包的例子,光从意图的字面含义上就很容易能够理解这个模式的用途,一个用户界面工具包包含了很多种控件(组件),这些组件有一定的风格(Style)因此他们是相关的,抽象工厂定义了一个抽象的接口去创建他们,从调用者的角度来讲很好的满足了依赖倒置原则。
2. 适用性
在以下情况可以使用Abstract Factory模式
一个系统要独立于它的产品的创建,组合和表示时
一个系统要由多个产品系列中的一个来配置时
当你要强调一系列相关的产品对象的设计以便进行联合使用时
当你提供一个产品类库,而只想显示它们的接口而不是实现时
这部分内容很好的反映了抽象工厂与其他模式之间的区别,第一是使用某个产品系列来配置系统,第二产品系列里的产品对象需要联合使用
我突然想到一个问题:如果有一个支持多数据库的系统,数据访问层的设计为什么无法用到抽象工厂?
SqlConnection, SqlCommand, SqlParameter, SqlAdapter可以认为是一系列相关的类,但是我们很难说用这些类去“配置”一个系统
有一些场景倒是和产品系列和配置有点相关,例如
装修一个房子,有中式和西式两种风格,对应不同的风格墙面的颜色,吊顶的设计,瓷砖的选择,厨房卫生间的整体风格都要一致,每部分的选材可以认为是一系列相关的对象,同时他们一起可以装饰(配置)我的房子
另一个例子是电脑的组装,电脑是系统,其中的零配件是具体的产品,而诸如“家用型电脑”,“商务办公型”,"游戏娱乐型“ 可以认为是不同的产品系列(ConcreteFactory)
3. 结构
4. 效果
在看具体代码前先看下设计模式一书中的概括
1) 它分离了具体的类
2)它使得易于交换产品系列
3)它有利于产品的一致性
4)难以支持新种类的产品
5. 实现
根据抽象工厂的特点,很容易想到将具体工厂实现为一个单例
另外在创建具体产品类时,可以采用简单工厂方法(Simple Factory)
class Program { static void Main(string[] args) { AbstractFactory factory = AbstractFactory.Instance("1"); AbstractProductA productA = factory.CreateProductA(); AbstractProductB productB = factory.CreateProductB(); //call product a and product b methods to do something } } class FactoryConfig { public static int type; } abstract class AbstractFactory { private static AbstractFactory _instance = null; public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); protected AbstractFactory() { } public static AbstractFactory Instance() { if (_instance == null) { if (FactoryConfig.type == 1) _instance = new ConcreteFactory1(); else if (FactoryConfig.type == 2) _instance = new ConcreteFactory2(); else throw new NotImplementedException(); } return _instance; } } class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } abstract class AbstractProductA { } abstract class AbstractProductB { } class ProductA1 : AbstractProductA { } class ProductA2 : AbstractProductA { } class ProductB1 : AbstractProductB { } class ProductB2 : AbstractProductB { }
注意上面的例子中 AbstractFactory类实现了一个单例,Instance 方法内部根据某个全局变量去创建ConcreteFactory
6. 缺点
很明显,当有新的产品系列出现时这个结构无法满足开放封闭原则
通俗的说就是当我们有中式,西式的装修风格,如果增加一种宫廷式装修风格那么势必增加很多类并且修改AbstractFactory
设计模式一书提出了可扩展的抽象工厂,个人认为这不是一个好主意(当然你可以通过传参数通过反射来实现)
设计无法做到完美,虽然增加产品系列会导致一系列的变化,但是好处是这个变化本身必须遵循这套结构,本质上不会增加什么复杂度,所以不必苛求
7. 扩展
上面的例子具体产品的对象创建没有用到工厂方法(Factory Method),既然抽象工厂涉及到的一系列产品是相关的,那么他们的创建也许就不像上面代码那样那么简单了
对于复杂对象的创建也许就要用到其他的设计模式了