定义
定义一个用于创建对象的接口,让子类决定具体实例化哪一个类,把一个类的实例化延迟到子类。
案例
现在有两种男人:程序员和其他男人,为了延续下一代,每个男人都需要找寻一个女人,但是每个男人都有每个男人的要求,有的要漂亮的,有的要有内涵的,有的要技术好的。这各种各样的女人就像一些列的产品,从Girl延伸出来的(Gril not woman),比如ThinGril、FatGirl。程序员都喜欢性感的Gril,所以创建Girl对象的时候都是new一个ThinGril,而其他的男人都喜欢FatGirl,就得到如下类图:
从上图可以看出每一个男人只能选择一个女人,因为这是受法律保护的。
从类图不难得到一下代码:
class Man {
public:
virtual Gril* createGirlFriend() = 0;
}
class Programmer : public Man {
public:
virtual Gril* createGrilGriend() {
return new ThinGirl();
}
}
class OtherMan: public Man {
public:
virtual Gril* createGrilGriend() {
return new FatGirl();
}
}
Man* man = new Programmer();
Girl* girl = man->createGrilFriend();
注意工厂方法有两种不同的情况:
- 类Man是一个抽象类,不提供工厂方法的实现。
- 类Man提供工厂方法的实现。
而且创建产品对象的时候还可以提供参数的形式来实例化对象:
class Man {
public:
virtual Gril* createGirlFriend(string hobby) {
if (hobby == "Normal")
return ThinGirl();
else
return FatGirl();
}
}
class OtherMan: public Man {
public:
virtual Gril* createGrilGriend(string hobby) {
// anyway
return new FatGirl();
}
}
Man* man = new Programmer();
Girl* girl = man->createGrilFriend();
从代码里可以看出其他的男人都有自己的路要走,不接受建议。
工厂方法还可以通过模版方法来避免创建子类:
class Man {
public:
virtual Gril* createGirlFriend() = 0;
}
template <typename TheGirl>
class OtherMan: public Man {
public:
virtual Gril* createGrilGriend() {
return new TheGirl();
}
}
Man* man = new NormalMan<BeautifulGirl>();
Girl* girl = man->createGrilFriend();
适用性
- 当一个类不知道它要具体创建什么产品类对象的时候。
- 当一个类希望由它的子类来创建产品类对象。
- 当一个类把创建产品类对象委托给自己的子类,而被委托的这一子类就是需要创建对象的代理者,和它息息相关。
相关模式
工厂方法模式:一个抽象工厂类派生多个具体工厂类,一个抽象产品类派生多个具体产品类。每个男人一个女人(一夫一妻)。
抽象工厂模式:一个抽象工厂类派生多个具体工厂类。多个抽象产品类派生多个具体产品类。每个男人多个女人(多妻制)。