设计原理
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
这里还是举特斯拉工厂的例子,工厂方法针对的只是一个产品等级结构的车系,而特斯拉旗下的还有更多不同的车系,对于每种车系又有不同的零件被生产并组装在一起,这就用到了抽象工厂。
来看两个概念:
产品等级结构 :产品等级结构即产品的继承结构。
产品族 :在抽象工厂模式中。
图中一共有四个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。
引进抽象工厂模式
所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:
UML类图
- 抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
- 具体工厂(Concrete
Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。 - 抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
- 具体产品(Concrete
Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
实现代码:
// Abstract Factory pattern -- Structural example
using System;
// "AbstractFactory"
abstract class AbstractFactory
{
// Methods
abstract public AbstractProductA CreateProductA();
abstract public AbstractProductB CreateProductB();
}
// "ConcreteFactory1"
class ConcreteFactory1 : AbstractFactory
{
// Methods
override public AbstractProductA CreateProductA()
{
return new ProductA1();
}
override public AbstractProductB CreateProductB()
{
return new ProductB1();
}
}
// "ConcreteFactory2"
class ConcreteFactory2 : AbstractFactory
{
// Methods
override public AbstractProductA CreateProductA()
{
return new ProductA2();
}
override public AbstractProductB CreateProductB()
{
return new ProductB2();
}
}
// "AbstractProductA"
abstract class AbstractProductA
{
}
// "AbstractProductB"
abstract class AbstractProductB
{
// Methods
abstract public void Interact( AbstractProductA a );
}
// "ProductA1"
class ProductA1 : AbstractProductA
{
}
// "ProductB1"
class ProductB1 : AbstractProductB
{
// Methods
override public void Interact( AbstractProductA a )
{
Console.WriteLine( this + " interacts with " + a );
}
}
// "ProductA2"
class ProductA2 : AbstractProductA
{
}
// "ProductB2"
class ProductB2 : AbstractProductB
{
// Methods
override public void Interact( AbstractProductA a )
{
Console.WriteLine( this + " interacts with " + a );
}
}
// "Client" - the interaction environment of the products
class Environment
{
// Fields
private AbstractProductA AbstractProductA;
private AbstractProductB AbstractProductB;
// Constructors
public Environment( AbstractFactory factory )
{
AbstractProductB = factory.CreateProductB();
AbstractProductA = factory.CreateProductA();
}
// Methods
public void Run()
{
AbstractProductB.Interact( AbstractProductA );
}
}
/// <summary>
/// ClientApp test environment
/// </summary>
class ClientApp
{
public static void Main(string[] args)
{
AbstractFactory factory1 = new ConcreteFactory1();
Environment e1 = new Environment( factory1 );
e1.Run();
AbstractFactory factory2 = new ConcreteFactory2();
Environment e2 = new Environment( factory2 );
e2.Run();
}
}
总结
模式扩展
“开闭原则”的倾斜性
“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。
增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。
抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。
抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。
参考连接
http://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/abstract_factory.html
http://blog.csdn.net/ipqxiang/article/details/1955677