本文使用C++来介绍生成器模式。
小新接到客户需求,需要建造一个房间,该房间非常简单,由门、窗和墙组成,客户希望通过CreateRoom函数来完成房间的建造。在上一节,小新使用抽象工厂模式,帮助客户解决了这个问题。
小新善于思考,再一次分析上一节抽象工厂模式方案。在该方案中,抽象工厂可以给客户返回Room(房间)、Door(门)、Window(窗)、Wall(墙)对象,客户将这些对象组装成目标房间对象。
“客户只是想要一个建好的房间,其实并不需要单独的门、窗和墙啊。”小新心想,能不能把门、窗和墙的建造都放在我的工厂中,最后直接返回给客户建好的房间呢?小新心里规划出生成器的模型,写出了以下代码。
class RoomBuilder {
public:
virtual void BuildRoom() { }
virtual void BuildDoor() { }
virtual void BuildWindow() { }
virtual void BuildWall() { }
virtual Room* GetRoom() { return 0; }
protected:
RoomBuilder();
};
客户可以按照如下方式使用RoomBuilder类。
Room* CreateRoom(RoomBuilder& builder) {
builder.BuildRoom();
builder.BuildDoor();
builder.BuildWindow();
builder.BuildWall();
return builder.GetRoom();
}
可以看到客户在使用过程中,并没有接触到门、窗和墙对象,客户通过发送指令(调用相应函数),所有的生成都在生成器中完成,最后最后客户通过指令(GetRoom)得到建好的房间。
有了这个生成器模型,小新的思路越发的清晰。客户如果要求建造一个木门(WoodenDoor)、隔音墙(SoundProofWindow)和绿墙(GreenWall),则派生出一个具体类即可,这里我们使用WsgRoomBuilder来命名(由于本文主要介绍设计模式,所以成员函数的实现直接写在类中,也没有相关安全性的检测)。
class WsgRoomBuilder : public RoomBuilder {
public:
RoomBuilder() { _currentRoom = 0; }
virtual void BuildRoom() { _currentRoom = new Room; }
virtual void BuildDoor() { WoodenDoor* aDoor = new WoodenDoor; _currentRoom->AddDoor(aDoor); }
virtual void BuildWindow() { SoundProofWindow* aWindow = new SoundProofWindow; _currentRoom->AddWindow(aWindow); }
virtual void BUildWall() { GreenWall* aWall = new GreenWall; _currentRoom->AddWall(aWall); }
virtual Room* GetRoom() { return _currentRoom; }
private:
Room* _currentRoom;
};
该类增加一个_currentRoom成员变量来存放建造过程中的房间,并在用户调用GetRoom时返回该对象。客户可以使用如下方式来建造房间。
WsgRoomBuilder builder;
Room* room = CreateRoom(builder);
要想建造红色的房间,则继承RoomBuilder类,并且重载BuildWall函数即可。
使用生成器模式,小新也可以完成客户的需求。那它和抽象工厂模式有什么区别呢?小新思考了以下总结如下:
1、生成器着重于结果的呈现,即着重于构造最终的对象。抽象工厂着重于多个产品。在该例中,生成器着重于生成最终的房间对象,而抽象工厂着重于将房间、门、窗、墙等产品交付客户,这也说明第二点区别。
2、生成器在最后一点返回产品,而抽象工厂立即返回过程中使用到的产品。也就是说,生成器将装配方式隐藏在类中。
生成器模式适用于以下情况(参考自《设计模式》)
1、当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2、当构造过程必须允许被构造的对象有不同的表示时。
生成器模式的效果包括(参考自《设计模式》)
1、因为生成器模式隐藏了产品的装配方式,因此它使你可以改变一个产品的内部表示。
2、它将构造代码和表示代码分开,如在本例中,客户不需要知道Door、Window、Wall的存在以及Room的AddDoor等方法。
3、它使你可对构造过程进行更精细的控制。