http://www.cnblogs.com/Reeezak/archive/2005/10/23/260493.html
Abstract Factory,把英文直接翻译过来的话就是“抽象工厂”,既然是工厂,那就肯定是生产产品的地方。不过,它不是生产同一类的产品,而是生产同一系列的产品。举个例子,广州本田现在生产3种汽车,Odyssey、Accord、Fit,而广本的工厂里面并不是拥有3条不同的生产线以生产不同的汽车。这就非常相似于我们正在讨论的抽象工厂模式,广本在生产不同的汽车时,需要在各个生产环节进行修改,换机器自然是不合适的,因为这3种汽车每天都要生产,分时段而已。如果某一个环节的更换工作出了问题都会有大麻烦,比如Fit的车顶肯定装不到Odyssey上。 我们在软件设计的时候也是这样,如果需要某一系列配套的类来进行工作,当这个系列中有一个类用错了,后果都是不好的。再回到广本的例子上,当广本准备生产 另外一种汽车时,只需要拥有相应的配套模具(还有其他的一些配件和一些数控设备的控制程序)就可以了,没有必要搞一大堆的生产线。
再来一个生活中的例子,西服+西裤+皮鞋+白衬衫+领带+头发梳得顺顺的,出入高级会所或者重要场合的时候,男人一般都这样穿;休闲装+运动鞋+随意的发型,生活中就这样穿,舒服;睡衣+拖鞋+鸡窝头,早上就这样。每一种都是合适的造型,如果你搞成如下这样的造型就不合适了,西服+西裤+回力鞋+超级大背包+鸡窝头,广州火车站很多同志都是这样打扮的。
抽象工厂模式是一种创建型的模式。上面的比喻说明了抽象工厂就是生产同一个系列产品的东西,因为这一系列的产品是关联的,如果混用就可能出问题,所以就统一的在抽象工厂中进行创建。当要增加一个新的产品系列时,就多写一个工厂子类并添加相应的产品子类就可以了。
我们来看一个类图。
图中,我们可以看到,客户需要得到某系列的产品的时候,直接用相应的工厂子类来创建产品就可以了。比如,当需要生产Fit时,就用FitFactory,等到换班之后,要生产Odyssey了,直接使用OdysseyFactory替换FitFactory就行了,至于怎么替换就随便了,GoF也给了我们一些建议,我将在后面总结创建型模式的时候讲。
把上面的类图转换成代码,应该是这个样子。
关于车门的类:
{
}
public class FitDoor : AbstractDoor
{
}
public class OdysseyDoor : AbstractDoor
{
}
关于底盘的类:
{
}
public class FitChassis : AbstractChassis
{
}
public class OdysseyChassis : AbstractChassis
{
}
关于工厂的类:
{
public abstract AbstractDoor CreateDoor();
public abstract AbstractChassis CreateChassis();
}
public class FitFactory
{
public AbstractDoor CreateDoor()
{
return new FitDoor();
}
public AbstractChassis CreateChassis()
{
return new FitChassis();
}
}
public class OdysseyFactory
{
public AbstractDoor CreateDoor()
{
return new OdysseyDoor();
}
public AbstractChassis CreateChassis()
{
return new OdysseyChassis();
}
}
客户的调用:
{
private AbstractDoor _door;
private AbstractChassis _chassis;
private HondaFactory _factory;
public void GetACar(string seriesName)
{
this.PrepareFactory(seriesName);
this._door = this._factory.CreateDoor();
this._chassis = this._factory.CreateChassis();
// TODO: Make a car!
}
private void PrepareFactory(string seriesName)
{
switch(seriesName)
{
case "Fit":
this._factory = new FitFactory();
break;
case "Odyssey":
this._factory = new OdysseyFactory();
break;
}
}
}
抽象工厂的优点很明显了,就是在需要用到一系列相关类的地方,它可以使我们不出错的创建出一系列的类实例,而我们在需要添加新的产品系列的时候,完全不需 要考虑其他系列的问题,仅需要将相关的抽象类(工厂已经产品)具体化就可以了。缺点也在这个地方,当工厂需要生产多一种产品(不是系列)的时候,改动将波 及所有类,比如,广本打算在每一辆汽车上装一个翅膀,那就需要在工厂中添加一个冲压机(以及各种车型的翅膀模具),还要在焊接科里添加这么一道工序,涂装 科以及总装科里面也一样要进行相应的调整。
工厂子类不一定需要实现父类的所有方法,但要使子类有用的话,我们必须使它的所有方法宣布具体化。这里,就引出几种做法:1、工厂父类可以就是一个接口,以确保其子类一定是具体的;2、我们可以继承抽象的父类,但不完全具体化,这样可以继续细分工厂子类;3、抽象的父类中含有具体的方法,这些方法也可以不加virtual修饰符。最后的这种方法可能是比较灵活一点的。
抽象工厂主要是用在需要一系列相关联的类协同工作的地方,而且这些系列的数量可能会变多,每一个系列完成的工作都不一样,但是调用接口却是一样的。另外,抽象工厂不适合这样一种情况,即每个系列内部的元素数量不能够确定,也就是说,当初设计的时候,系列中有 3 个配件,后面又涨成 5 个,之后又涨到 7 个,这样的话,要改动的地方将多到让人受不了。