---
# System prepended metadata

title: Blog 4｜設計模式 - 創建者模式
tags: [部落格]

---

# Blog 3｜設計模式 - 創建型模式

- Reference :
    - https://shengyu7697.github.io/archives/
    - https://www.jyt0532.com/
    - https://refactoringguru.cn/design-patterns/catalog

## (0)簡單工廠模式 Simple Factory
- `將建立邏輯集中在一個工廠中`
- `不符合開放封閉原則`
- 不被視為一個正式的設計模式，更像是一個寫程式技巧
- 常被宣告成 static 如此就不需要事先準備實體化的工廠，但是也造成無法繼承並修改 create 方法
```c++=
class Phone {
public:
    virtual ~Phone() = default;
};
class Samsung : public Phone {};
class Pixel : public Phone {};
class Iphone : public Phone {};

class phoneFactory {
public:
    static std::unique_ptr<Phone> createPhone(const std::string& phoneType) {
        if (phoneType == "Iphone") {
            return std::make_unique<Iphone>();
        } else if (phoneType == "Samsung") {
            return std::make_unique<Samsung>();
        } else if (phoneType == "Pixel") {
            return std::make_unique<Pixel>();
        } else {
            return nullptr;
        }
    }
};
```
## (1)工廠方法模式 Factory Method
- `將物件的建立過程，延遲到子類別進行`
- 符合`「開放封閉原則」`
- ![image](https://hackmd.io/_uploads/BJRrqYmkJe.png)
```c++=
class PhoneFactory {
    virtual std::unique_ptr<Phone> createPhone() = 0;
};

// ConcreteCreator 1
class IphoneFactory : public PhoneFactory {
    std::unique_ptr<Iphone> createPhone() override {
        return std::make_unique<Iphone>();
    }
};

// ConcreteCreator 2
class SamsungFactory : public PhoneFactory {
    std::unique_ptr<Samsung> createPhone() override {
        return std::make_unique<Samsung>();
    }
};
```
## (2)抽象工廠模式 Abstract Factory
- 特別適合 `GUI元件` 在跨平台上的應用
- 工廠方法模式的延伸
    - 工廠方法模式：每個工廠建立`一個產品`
    - 抽象工廠模式：每個工廠建立`一系列產品`
- ![image](https://hackmd.io/_uploads/SyaDqFX1Je.png)
- 參考資料：[Ref1](https://shengyu7697.github.io/cpp-abstract-factory-pattern/) / [Ref2](https://refactoringguru.cn/design-patterns/abstract-factory)
```c++=
class GUIFactory {
public:
    virtual std::unique_ptr<Button> createButton() = 0;
    virtual std::unique_ptr<TextBox> createTextBox() = 0;
    virtual ~GUIFactory() = default;
};

// Concrete Factory 1
class WindowsGUIFactory : public GUIFactory {
public:
    std::unique_ptr<Button> createButton() override {
        return std::make_unique<WindowsButton>();
    }
    std::unique_ptr<TextBox> createTextBox() override {
        return std::make_unique<WindowsTextBox>();
    }
};

// Concrete Factory 2
class MacGUIFactory : public GUIFactory {
public:
    std::unique_ptr<Button> createButton() override {
        return std::make_unique<MacButton>();
    }
    std::unique_ptr<TextBox> createTextBox() override {
        return std::make_unique<MacTextBox>();
    }
};
```
## (3)建造者模式 Builder
- 將物件的建立過程分解為多個步驟，根據需求排列組合
- ![image](https://hackmd.io/_uploads/B1kKpK7y1l.png)
```c++=
// concrete builder
class LuxuryCarBuilder {
private:
    Car* car;

public:
    LuxuryCarBuilder() {
        car = new Car();
    }

    void buildEngine() {
        car->setEngine("V8 Turbo Engine");
    }

    void buildWheels() {
        car->setWheels("Alloy Wheels");
    }

    void buildInterior() {
        car->setInterior("Leather Interior");
    }

    Car* getCar() {
        return car;
    }
};

// client
CarBuilder* builder = new LuxuryCarBuilder();
builder->buildEngine();
builder->buildWheels();
builder->buildInterior();
Car* car = builder->getCar();
```

## (4)原型模式 Prototype
- 替原有的類別提供複製的介面
- 先建立一個原型，接著快速複製這個原型
- 在C++中，這通常是透過深拷貝或淺拷貝來實現的
    - 原型模式的缺點在於`複製過程的複雜性`。當物件的結構非常複雜或包含指標、動態分配的資源時，正確地實現深拷貝可能會變得困難
```c++=
class Shape {
    virtual Shape *clone() = 0;
}

class Rectangle : Shape {
private:
    int w;
    int h;
public:
    Rectangle(int _w, int _h) : w(_w), h(_h) {}
    Shape *clone() const override {
        return new Rectangle(*this)
    }
}

```
## (5)單一實例模式 Singleton
- 保證一個類別只有一個實例
- 要注意 `多執行緒同時存取` 單一實例的問題
- ![image](https://hackmd.io/_uploads/r1RTe5mkyx.png)
- (1)餓漢模式（Eager Singleton）
```c++=
class EagerSingleton {
private:
    EagerSingleton() {}

    static EagerSingleton instance;

public:
    EagerSingleton(const EagerSingleton&) = delete;
    EagerSingleton& operator=(const EagerSingleton&) = delete;

    static EagerSingleton& getInstance() {
        return instance;
    }
};
// 在 main 開始之前就初始化
EagerSingleton EagerSingleton::instance;
```
- (2)懶漢模式（Lazy Singleton）
```c++=
class LazySingleton {
private:
    LazySingleton() {}
    static LazySingleton* instance;
    static std::mutex mtx;

public:
    LazySingleton(const LazySingleton&) = delete;
    LazySingleton& operator=(const LazySingleton&) = delete;

    static LazySingleton* getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx); // thread safe
            if (instance == nullptr) {
                instance = new LazySingleton();
            }
        }
        return instance;
    }
};

// 初始化
LazySingleton* LazySingleton::instance = nullptr;
std::mutex LazySingleton::mtx;
```
- (3) Meyers Singleton
```c++=
class MeyersSingleton {
private:
    MeyersSingleton() {}

public:
    MeyersSingleton(const MeyersSingleton&) = delete;
    MeyersSingleton& operator=(const MeyersSingleton&) = delete;
    
    static MeyersSingleton& getInstance() {
        static MeyersSingleton instance;
        return instance;
    }
};
```
