---
# System prepended metadata

title: Builder
tags: [Design Pattern]

---

---
tags: Design Pattern
---

# Builder

在網路上找到一篇介紹很清楚的文章，會放到下方的參考，真的寫得很好，讓我一看就懂，我待會會試著用自己的方式來講。

I found an article with a very clear introduction on the Internet, and I will put it in the reference below. It is really well written, and I can understand it at a glance. I will try to explain it in my own way later.

## define:

建造者 (Builder) 模式將物件的「建構」與「表示」分離，隱藏並封裝建構過程的細節。它讓我們可以將物件本身拆解成不同的元件，一步一步建造每一部分，最後產生出我們想要的複雜物件。

Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

<font color="#f00">advantage:</font>

1. The client does not need to know the details of the internal composition of the product, and the product itself is decoupled from the product creation process, so that the same creation process can create different product objects


<font color="#f00">disadvantage:</font>

1. If the internal changes of the product are complex, it may result in the need to define many specific builder classes to implement such changes, resulting in a very large system.

---

## time to use

宣告一個物件需要太長的建構子

什麼意思呢?

文章作者用這樣來比喻，如果我要創造一個房子物件，最簡單的方式就是在建構子賦予它該有的屬性如: 窗戶數、門數、房間數、座標等等；假設如果有些房子還要其他的屬性呢，也許還要繼承他去擴充；這樣會導致建構子參數很冗長，很難一目了然；所以透過Builder，可以拆解元件製造的過程，只保留需要建的的部分屬性，讓建構的意圖清晰很多。

Declaring an object requires a constructor that is too long

What does that mean?

The author of the article uses this analogy. If I want to create a house object, the easiest way is to give it the attributes it should have in the constructor, such as: the number of windows, the number of doors, the number of rooms, the coordinates, etc.; As for other properties, they may have to be inherited and expanded; this will lead to very long constructor parameters and it is difficult to understand at a glance; so through the Builder, the process of component manufacturing can be disassembled, and only part of the properties that need to be built are retained, so that the constructor can The intent is much clearer.

---

shape_builder.h

這邊是透過builder來建造物件，個人覺得沒有用到builder的精隨，只是讓compound的建造更明顯其意圖。

This is to build objects through the builder. Personally, I don't think the builder's essence is used. It just makes the construction of the compound more obvious.


```cpp=
#pragma once

// #include "../shape.h"

#include "../circle.h"
#include "../rectangle.h"
#include "../triangle.h"
#include "../two_dimensional_vector.h"
#include "../compound_shape.h"

#include <stack>
#include <list>

class ShapeBuilder
{
public:
    // assignment6
    static ShapeBuilder *getInstance()
    {
        if (_instance == nullptr)
        {
            _instance = new ShapeBuilder();
        }

        return _instance;
    }

    ~ShapeBuilder()
    {
        this->reset();
    }

    void buildCircle(double radius)
    {

        _shapes.push(new Circle(radius));
    }

    void buildRectangle(double length, double width)
    {

        _shapes.push(new Rectangle(length, width));
    }

    void buildTriangle(double x1, double y1, double x2, double y2)
    {

        TwoDimensionalVector vec1(x1, y1);
        TwoDimensionalVector vec2(x2, y2);
        _shapes.push(new Triangle(vec1, vec2));
    }

    //start build CompoundShape
    void buildCompoundBegin()
    {

        _shapes.push(new CompoundShape());
    }

    //end build CompoundShape
    void buildCompoundEnd()
    {
        std::list<Shape *> components;

        while (typeid(*_shapes.top()) != typeid(CompoundShape) ||
               (!_shapes.top()->createIterator()->isDone() &&
                typeid(*_shapes.top()) == typeid(CompoundShape)))
        {
            components.push_back(_shapes.top());
            _shapes.pop();
        }
        Shape *compound = _shapes.top();
        for (auto it = components.rbegin(); it != components.rend(); it++)
        {
            compound->addShape(*it);
        }
    }

    Shape *getShape()
    {
        return _shapes.top();
    }
    
    void reset() { _instance = 0; }

private:
    std::stack<Shape *> _shapes;

    static inline ShapeBuilder *_instance = nullptr;
    ShapeBuilder(){};
};

```
---

test

```cpp=
TEST_F(CaseBuilder, BuildCompound)
{
    ShapeBuilder *builder = ShapeBuilder::getInstance();

    builder->buildCompoundBegin();
    builder->buildCircle(1.0);
    builder->buildCircle(2.0);
    builder->buildCompoundEnd();
    Shape *result = builder->getShape();

    ASSERT_NEAR(1 * 1 * M_PI + 2 * 2 * M_PI, result->area(), delta);
    delete result;
    delete builder;
}
```


The relevant code is in: https://github.com/andy091045/Design-Pattern/tree/main/posd2021f-hw7/posd2021f_110598066_hw

reference: https://medium.com/wenchin-rolls-around/%E8%A8%AD%E8%A8%88%E6%A8%A1%E5%BC%8F-%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F-builder-design-pattern-7c8eac7c9a7