定义一个创建对象的接口,让子类决定实例化哪个产品类。工厂方法使一个对象的创建延迟到子类。
当一个类不知道它要创建的对象的类时。
当一个类希望由它的子类来决定创建哪个类的对象时。
当一个类决定将创建对象委托给多个子类,并且希望将那个子类是代理这一信息局部化的时候。

Creater:
声明工厂方法的抽象类,工厂方法返回一个产品类(Product)。
可以调用工厂方法返回一个产品对象。
ConcreteCreater:
重定义工厂方法,以返回一个特定的product。
Product:
产品抽象类,给用户提供一致的产品接口。
ConcreteProduct:
特定的产品,实现product接口。
工厂方法将特定的类的实例化延迟到子类,而且返回product接口,使用户代码不用和具体类打交道,一致的对待Product。所以在用户要加入新产品的时候,无需更改客户代码,只需加入一个新的ConcreteProduct和ConcreteCreater即可,这个也是遵 守了“开放封闭原则”。
连接平行的类层次,上面的结构图中,ConcreteCreater1对应创建ConcreterProduct1而ConcreteCreater2对应创建ConcreterProduct2。所以creater和product的类层次是平行的,用户只需选定一个Creater,就创建出对应的product。像是一个map一样,不会出现牛头不对马嘴之态。
Creater有两种实现,一种就是抽象的工厂方法,具体实现留到子类。另一种就是有一个缺省的实现,子类也可以重新实现这个方法。这种方法使用于真的有一个默认的Product需要实例化的这种情况
带参数的工厂方法,这种情况可以创建多种产品,不过有个限制就是所有产品都要实现product接口,否则就失去工厂方法的意义了。代码如下:
Product* ConcreteCreater1::FactoryMethod(int nID)
{
If(nID == BUTTON)
{
return new button;
}
Else if(nID == BOX)
{
return new box;
}
…
}
用模板实现,省略创建子类。
class Creater
{
public:
virtual Product* FactoryMethod() = 0;
};
template<class theProduct>
class TempCreater: public Creater
{
virtual Product* FactoryMethod();
};
template<class theProduct>
Product* TempCreater<theProduct>::FactoryMethod()
{
return new theProduct;
}
使用这个模版客户端只需定义产品,而不需定义creater的子类。
在一个ACT游戏中,主角过关过程中有许多敌人,如狼(wolf),蝙蝠(bat),老怪(BOSS),在每一关的刚开始就要创建许多不同的敌人,如果不用工厂方法,则把所有的创建任务都放在了客户代码中,则一个代码不易扩充和修改,二是代码很杂乱。而用了工厂方法则可以克服这两个缺点。比如你增加一个新的敌人-恐龙,则只需增加一个恐龙类(ConcreteProduct),再增加一个创建恐龙的类(ConcreteCreater )就OK了。
源码如下:
class Enemy
{
public:
virtual void attack() = 0;
virtual void Draw() = 0;
virtual ~Enemy() = 0;
};
// concrete product class
class Wolf : public Enemy
{
void attack()
{
cout << "Wolf attack me!" << endl;
}
void Draw()
{
cout << "I am Wolf!" << endl;
}
};
// concrete product class
class Bat : public Enemy
{
void attack()
{
cout << "Bat attack me!" << endl;
}
void Draw()
{
cout << "I am Bat!" << endl;
}
};
// concrete product class
class Boss : public Enemy
{
void attack()
{
cout << "Boss attack me!" << endl;
}
void Draw()
{
cout << "I am Boss!" << endl;
}
};
// creater abstract class
class EnemyCreater
{
virtual Enemy* CreateEnemy() = 0;
};
// concrete creater class
class WolfCreater : public EnemyCreater
{
Enemy* CreateEnemy()
{
return new Wolf;
}
};
// concrete creater class
class BatCreater : public EnemyCreater
{
Enemy* CreateEnemy()
{
return new Bat;
}
};
// concrete creater class
class BossCreater : public EnemyCreater
{
Enemy* CreateEnemy()
{
return new Boss;
}
};
int main(int argc, char* argv[])
{
EnemyCreater* enemyCreater[3];
enemyCreater[0] = new WolfCreater;
enemyCreater[1] = new BatCreater;
enemyCreater[2] = new BossCreater;
Enemy* cruEnemy = NULL;
for(int i = 0; i < 3; ++i)
{
cruEnemy = enemyCreater[i].CreateEnemy();
cruEnemy->Draw();
cruEnemy->attack();
delete cruEnemy;
}
return 0;
}
Abstract Factory经常用工厂方法来实现。
工厂方法通常在Template Methods中被调用。
Prototypes不需要创建Creater的子类。但是,它们通常要求一个针对Product类的Initialize操作。Creater使用Initialize来初始化对象。而Factory Method不需要这样的操作
《设计模式精解》清华大学出版社,熊杰译。
《设计模式可复用面向对象软件的基础》机械工业出版社,四人团著。