Design pattern learning summary: Builder pattern (Builder)

1. Scene analysis

2. Intent

Separates the construction of a complex object from its representation so that the same construction process can create different representations.

3. Applicability

  1. When an algorithm for creating a complex object should be independent of the object's constituent parts and their mode of assembly.
  2. The construction process must allow for different representations of the objects being constructed.

4. Structure

Write picture description here
Director: Constructs an object using the Builder interface.
Builder: Specifies the abstract interface for each component that creates a Product object.
ConcreteBuilder: A concrete constructor that implements the Builder interface to construct and equip the various components of the product.
Product: the complex object being constructed

5. Effect

  1. It allows you to change the internal representation of a product. Builder provides Director with an abstract interface for constructing products, which enables Builder to hide the representation and internal structure of the product, and it also hides how the product is assembled.
  2. It separates construction code from presentation code. The Builder pattern improves object modularity by encapsulating the creation and representation of a complex object.
  3. It gives you finer control over the construction process.

6. Achieve

1> Usually there is an abstract Builder class that defines an operation for each component that the Director may require to create, which usually does nothing by default , and a ConcreteBuilder redefines the corresponding operation for the components it is interested in creating.
2> The interface of the Builder class must be common enough to construct products for various types of concrete builders. Another key design issue is that you may need access to product components that have been built before, for example: first create a house, then create a door on the house. In this case, usually the builder will return the created child nodes to the director, and then the director will pass them back to the builder to continue building the product.
3> Products usually do not have abstract classes, because the products generated by the generator usually have huge differences in performance, and there is no need to define a common parent class.

7. Code example

We will implement a maze generator object, the code is as follows:

#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();
}



Guess you like

Origin blog.csdn.net/m0_37979033/article/details/79040785