参考
http://www.cnblogs.com/zhenyulu/articles/36885.html
http://wenku.baidu.com/view/a15af4186c85ec3a87c2c584.html
http://wenku.baidu.com/view/72d8f47b27284b73f24250f2.html
代码亲自调试
一 抽象工厂(Abstract Factory)模式
抽象工厂模式(AbstactFactoryPattern)是所有形态的工厂模式中最为抽象和最其一般性的。
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
据说最早的应用是用来创建在不同操作系统的视窗环境下都能够运行的系统。比如在Windows与Unix系统下都有视窗环境的构件,在每一个操作系统中,都有一个视窗构件组成的构件家族。我们可以通过一个抽象角色给出功能描述,而由具体子类给出不同操作系统下的具体实现。
二 Abstract Factory模式的结构
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
三 深入分析
抽象工厂模式是在当产品有多个抽象角色的时候使用的一种创建型设计模式。
按照里氏代换原则,凡是父类适用的地方,子类也必然适用。而在实际系统中,我们需要的是和父类类型相同的子类的实例对象,而不是父类本身,也就是这些抽象产品的具体子类的实例。具体工厂类就是来负责创建抽象产品的具体子类的实例的。
当每个抽象产品都有多于一个的具体子类的时候,工厂角色是如何确定实例化哪一个子类呢?例如说有两个抽象产品角色,而每个抽象产品角色都有两个具体产品。
抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。
每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。
何谓产品族?产品族是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。
对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。
由于每个具体工厂角色都需要负责不同等级结构的产品对象的创建,因此每个工厂角色都需要提供相应数目的工厂方法,分别用于创建相应数目的等级结构的产品。
四 试用情况
在以下情况下应当考虑使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
- 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
- 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
五 例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FactoryAbstract
{
// 抽象食草动物
abstract class Herbivore
{
}
// 抽象食肉动物
abstract class Carnivore
{
abstract public void Eat(Herbivore h);
}
// 继承的食草动物子类Widebeest
class Widebeest : Herbivore
{
}
// 继承的食肉动物子类Lion
class Lion : Carnivore
{
public override void Eat(Herbivore h)
{
Console.WriteLine(this+"eats"+h);
}
}
// 继承的食草动物子类Bison
class Bison : Herbivore
{
}
// 继承的食肉动物子类Wolf
class Wolf : Carnivore
{
public override void Eat(Herbivore h)
{
Console.WriteLine(this + "eats" + h);
}
}
// 抽象的工厂类
abstract class LandFactory
{
abstract public Herbivore CreateHerbivore();
abstract public Carnivore CreateCarnivore();
}
// 抽象工厂子类 - 非洲大陆工厂
class AfricaFactory : LandFactory
{
public override Herbivore CreateHerbivore()
{
return new Widebeest();
}
public override Carnivore CreateCarnivore()
{
return new Lion();
}
}
// 抽象工厂子类 - 美洲大陆工厂
class AmericaFactory : LandFactory
{
public override Herbivore CreateHerbivore()
{
return new Bison();
}
public override Carnivore CreateCarnivore()
{
return new Wolf();
}
}
// 客户端
class AnimalWorld
{
private Herbivore herbivore;
private Carnivore carnivore;
public AnimalWorld(LandFactory factory)
{
carnivore = factory.CreateCarnivore();
herbivore = factory.CreateHerbivore();
}
public void RunFoodChain()
{
carnivore.Eat(herbivore);
}
}
class Game
{
static void Main(string[] args)
{
LandFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld(africa);
world.RunFoodChain();
LandFactory america = new AmericaFactory();
world = new AnimalWorld(america);
world.RunFoodChain();
}
}
}
结果
六 优缺点
优点:
客户端不再负责对象的具体创建,而是把这个责任交给了具体的工厂类,客户端之负责对对象的调用。
当具有产品家族性质的产品被涉及到一个工厂类中后,对客户端而言是非常友好的,更重要的是如果想要更换为另外一产品家族,所要做的只是需要增加相应的产品家族成员和增加一个具体的产品工厂而已。
缺点:
当有新的产品加入的时候,也就是当产品的结构发生改变时,修要修改抽象工厂类的设计,这就导致了必须修改所有的具体工厂类,导致很客观的工作量的增加。
"开放-封闭"原则要求系统对扩展开放,对修改封闭。通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
增加产品族:Abstract Factory很好的支持了"开放-封闭"原则。
增加新产品的等级结构:需要修改所有的工厂角色,没有很好支持"开放-封闭"原则。
综合起来,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。