设计模式 — 抽象工厂模式 (AbstractFactory)

本文将借助C++来介绍抽象工厂模式。

设想小新接到客户需求,需要建造一个房间,该房间非常简单,由门、窗和墙组成。客户希望通过CreateRoom函数来完成房间的建造。

小新创建了四个类Room、Door、Window、Wall分别表示房间、门、窗和墙,很快完成了该函数的实现。

Room* CreateRoom() {
    Room* aRoom = new Room;
    Door* aDoor = new Door;
    Window* aWindow = new Window;
    Wall* aWall = new Wall;
    
    aRoom->AddDoor(aDoor);
    aRoom->AddWindow(aWindow);
    aRoom->AddWall(aWall);

    return aRoom;
}

客户使用这几行代码轻松的建了一个房间,非常高兴,于是又提出来想再建造一个房间,不过这次要木门、隔音窗和绿墙。小新很高兴,这不是和之前一样嘛,马上派生出三个类WoodenDoor、SoundProofWindow、GreenWall来表示木门、隔音窗和绿墙,并告诉客户,把之前的Door、Window和Wall都替换成新的就行了,客户看了后直皱眉头,对小新说,能不能把新型房间的建造变得简单点,每次都需要修改这么多地方,万一有个地方遗漏了,那损失就大了。

回到家后小新开始反省自己的松懈和冲动,也开始思考客户的需求。怎样才能让CreateRoom和房间的实现分离呢?怎样才能让CreateRoom易于产生新型房间呢?怎样才能让门窗墙的创建根据需求指向不同的实现呢?敏锐的小新马上想起了多态。手指一阵敲击,小新写出了下面的类。

class RoomFactory {
public:
    RoomFactory();

    virtual Room* MakeRoom() const
        { reutrn new Room; }
    virtual Door* MakeDoor() const
        { return new Door; }
    virtual Window* MakeWindow() const
        { return new Window; }
    virtual Wall* MakeWall() const
        { return new Wall; }
};

CreateRoom的实现也变成了下面的方式。

Room* CreateRoom (RoomFactory& factory) {
    Room* aRoom = factory.MakeRoom();
    Door* aDoor = factory.MakeDoor();
    Window* aWindow = factory.MakeWindow();
    Wall* aWall = factory.MakeWall();

    aRoom->AddDoor(aDoor);
    aRoom->AddWindow(aWindow);
    aRoom->AddWall(aWall);

    return aRoom;
}

CreateRoom通过传入函数中的RoomFactory对象来完成房间的创建。小新很清楚,因为RoomFactory的成员函数是虚函数,因此可以通过虚表指针指向派生类中的相关实现。为了实现客户要求的新房间,小新马上实现了一个新类,这里取WoodenDoor、SoundProofWindow、GreenWall的首字母来命名该类为WsgRoomFactory。

class WsgRoomFactory : public RoomFactory {
public:
    WsgRoomFactory();

    virtual WoodenDoor* MakeDoor() const
        { return new WoodenDoor; }
    virtual SoundProofWindow* MakeWindow() const
        { return new SoundProofWindow; }
    virtual GreenWall* MakeWall() const
        { return new GreenWall; }
};
第二天见到客户,小新自信的拿出了自己的新方案,首先创建了一个原始房间。

RoomFactory rf;
CreateRoom(rf);
然后将RoomFactory替换成WsgRoomFactory,创建了一个新型房间。

WsgRoomFactory wrf;
CreateRoom(wrf);
客户看了后很高兴,不住夸赞小新业务好,小新一激动,又造个红色的房间。

public RRoomFactory : public RoomFactory {
public:
    RRoomFactory();

    virtual RedWall* MakeWall() const
        { return new RedWall; }
};
RRoomFactory rrf;
CreateRoom(rrf);
并且告诉客户,我们的RoomFactory就是一个工厂,您想要什么房间、门、窗和墙,我们事先把产线给配好,您尽管拿去装配。

经过这两天的工作,小新总结如下(参考《设计模式》一书):

抽象工厂模式的适用场景如下:

1、系统独立与产品的创建,如本例中房间的构建方式并不影响CreateRoom函数内的代码实现。

2、系统需要由多个配置中的某一项实现,如本例中房间的构建可以选择普通、木隔音绿和红三种方式中的一个。

3、想只提供类的接口而不是实现时,如本例中,CreateRoom函数并不知晓RoomFactory中的具体实现,只是调用了相应接口。

4、当你要强调一系列相关的产品对象的设计以便进行联合使用时。

使用抽象工厂模式的优点:

1、系统与类的实现分离。

2、易于更换产品。

3、有利于产品的一致性。

总结完后,小新非常高兴,有点飘飘然,这时候接到了客户的电话,是不是又要夸奖我?小新窃喜。

“小新啊,前面干的不错,现在我需要造一间有床的房子。”

小新收起了笑容。这便是抽象工厂模式的缺点:难以扩展抽象工厂来产生新种类产品,因为添加或者删除接口会影响到所有子类的使用。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值