设计模式学习总结:生成器模式(Builder)

1.场景分析

2.意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

3.适用性

  1. 在创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配模式时。
  2. 当构建过程必须允许被构建的对象有不同的表示。

4.结构

这里写图片描述
Director:构建一个使用Builder接口的对象。
Builder:为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder:具体的构造器,实现Builder的接口以构造和装备该产品的各个部件。
Product:被构造的复杂对象

5.效果

  1. 它使你可以改变一个产品的内部表示。Builder提供给Director一个构造产品的抽象接口,该接口使得生成器可以隐藏这个产品的表示与内部结构,它同时也隐藏了该产品是如何装配的。
  2. 它将构造代码和表示代码分开了。Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。
  3. 它使你可对构造过程进行更精细的控制。

6.实现

1>通常有一个抽象的Builder类为Director可能要求创建的每一个构件定义一个操作,其缺省情况下通常什么都不做,而一个ConcreteBuilder对其有兴趣创建的组件重定义相应的操作。
2>Builder类的接口必须足够普通,以便为各种类型的具体生成器构造产品。另一个关键的设计问题是你可能需要访问前面已经构建了的产品组件,比如:先创建一个房子,然后在房子上创建一扇门。这种情况下,通常生成器会将创建的子节点返回给Director,然后Director将它们传回给Builder去继续构建产品。
3>产品通常没有抽象类,因为由生成器生成的产品,它们的表现差异通常十分巨大,没有定义公共父类的必要。

7.代码示例

我们将实现一个迷宫生成器对象,代码如下:

#include <iostream>
using namespace std;

#define SOUTH 0;
#define NORTH 1;
#define WEST  2;
#define EAST  3;
//墙
class Wall
{
public:
    Wall(){}
};
//房间
class Room
{
public:
    Room(int roomId){}
    void setSide(int direction, Wall *wall);
};
//门
class Door
{
    Door(Room *r1, Room *r2){}
};
//迷宫
class Maze
{
public:
    Room *getRoom(int roomId){}
    void addRoom(Room *room){}
};

class MazeBuilder
{
public:
    //创建迷宫
    virtual void buildMaze();
    //创建一个有特定房间号的房间
    virtual void buildRoom(int roomId);
    //在两个房间之间创建一扇门
    virtual void buildDoor(int roomFrom, int roomTo);

    virtual Maze *getMaze() { return nullptr; }

protected:
    //构造函数设为保护成员
    MazeBuilder();
};

//迷宫游戏类,担任Director的角色
class MazeGame
{
public:
    //通过一个MazeBuilder来创建一个迷宫
    Maze *createMaze(MazeBuilder *mazeBuilder)
    {
        mazeBuilder->buildMaze();
        mazeBuilder->buildRoom(1);
        mazeBuilder->buildRoom(2);
        mazeBuilder->buildDoor(1, 2);

        return mazeBuilder->getMaze();
    }
};

//具体的构造器
class StandardMazeBuilder : public MazeBuilder
{
public:
    StandardMazeBuilder(){}

    void buildMaze() override
    {
        _curMaze = new Maze();
    }

    void buildRoom(int roomId) override
    {
        if (!_curMaze->getRoom(roomId))
        {
            Room *room = new Room(roomId);
            _curMaze->addRoom(room);
            room->setSide(NORTH, new Wall());
            room->setSide(SOUTH, new Wall());
            room->setSide(EAST, new Wall());
            room->setSide(WEST, new Wall());
        }
    }

    void buildDoor(int roomFrom, int roomTo) override
    {
        Room *r1 = _curMaze->getRoom(roomFrom);
        Room *r2 = _curMaze->getRoom(roomTo);
        Door *door = new Door(r1, r2);
        r1->setSide(CommonWall(r1, r2), door);
        r2->setSide(CommonWall(r1, r2), door);
    }

    Maze *getMaze() { return _curMaze; }

private:
    int CommonWall(Room *, Room *);
    Maze *_curMaze = nullptr;
};

//使用
int main()
{
    Maze *maze;
    MazeGame game;
    StandardMazeBuilder builder;

    game.createMaze(&builder);
    maze = builder.getMaze();
}



猜你喜欢

转载自blog.csdn.net/m0_37979033/article/details/79040785
今日推荐