iT邦幫忙

2023 iThome 鐵人賽

DAY 21
0
Software Development

深入淺出設計模式 - 使用 C++系列 第 21

[Day 21] 拆解複雜物件的建立 - 生成器模式 (Builder Pattern)

  • 分享至 

  • xImage
  •  

Intent

  • Builder is a creational design pattern that lets you construct complex objects step by step
    • https://ithelp.ithome.com.tw/upload/images/20231003/20138643wWL1Qf8ATR.png

組成

  • Builder: 用來定義建構物件過程中各必要步驟 (方法) 的介面
  • Director: 負責指揮 ConcreteBuilder 該如何建構物件
  • ConcreteBuilder: 實作 Builder 介面,實際用來建構物件的類別
  • Product: 最終要被建立出來的物件類別
    https://ithelp.ithome.com.tw/upload/images/20231004/20138643LeRKqwvvFB.jpg

範例: 簡易 Bootloader 設計

  • 在嵌入式系統開發中,Bootloader 通常負責初始化硬體並 Load 後續的 Firmware 或 OS (取決於產品的複雜程度)
  • 這個過程可能涉及多個步驟,例: 初始化記憶體、設定時鐘、驗證軟體簽名 (Security)...等
typedef struct {
    void (*initMemory)();
    void (*setClock)();
    void (*verifySignature)();
    void (*loadKernel)();
    void (*bootKernel)();
} BootloaderBuilder;

void buildBootloader(BootloaderBuilder* builder) {
    if(builder->initMemory) {
        builder->initMemory();
    }
    if(builder->setClock) {
        builder->setClock();
    }
    if(builder->verifySignature) {
        builder->verifySignature();
    }
    if(builder->loadKernel) {
        builder->loadKernel();
    }
    if(builder->bootKernel) {
        builder->bootKernel();
    }
}

void initMemoryFunction() {
    // Initialize DDR, Cache, MMU
}

void setClockFunction() {
    // Initialize PLL and set CPU clock frequency
}

void verifySignatureFunction() {
    // Verify the digital signature of the OS image
}

void loadKernelFunction() {
    // Load the OS kernel from storage
}

void bootKernelFunction() {
    // Transfer control to the OS
}

int main() {
    // 初始化 builder,可以自由抽換 init Function
    BootloaderBuilder builder = {
        .initMemory = initMemoryFunction,
        .setClock = setClockFunction,
        .verifySignature = verifySignatureFunction,
        .loadKernel = loadKernelFunction,
        .bootKernel = bootKernelFunction
    };
    // 呼叫 builder (BootLoader)
    buildBootloader(&builder);
}

範例: 腳踏車組裝

// Represents a product created by the builder
class Bicycle {
public:
    Bicycle(std::string make, std::string model, std::string colour, int height)
        : Make(make), Model(model), Colour(colour), Height(height) {}

    std::string Make;
    std::string Model;
    int Height;
    std::string Colour;
};

// The builder abstraction
class IBicycleBuilder {
public:
    virtual std::unique_ptr<Bicycle> GetResult() = 0;

    virtual std::string GetColour() = 0;
    virtual void SetColour(std::string colour) = 0;

    virtual int GetHeight() = 0;
    virtual void SetHeight(int height) = 0;
};

// Concrete builder implementation.
class GTBuilder : public IBicycleBuilder {
public:
    std::unique_ptr<Bicycle> GetResult() override {
        return Height == 29 ? std::make_unique<Bicycle>("GT", "Avalanche", Colour, Height) : nullptr;
    }

    std::string GetColour() override { return Colour; }
    void SetColour(std::string colour) override { Colour = colour; }

    int GetHeight() override { return Height; }
    void SetHeight(int height) override { Height = height; }

private:
    std::string Colour;
    int Height;
};

// The director.
class MountainBikeBuildDirector {
public:
    MountainBikeBuildDirector(std::unique_ptr<IBicycleBuilder> builder)
        : builder(std::move(builder)) {}

    void Construct() {
        builder->SetColour("Red");
        builder->SetHeight(29);
    }

    std::unique_ptr<Bicycle> GetResult() {
        return builder->GetResult();
    }

private:
    std::unique_ptr<IBicycleBuilder> builder;
};

// Client code
int main() {
    auto director = std::make_unique<MountainBikeBuildDirector>(std::make_unique<GTBuilder>());
    director->Construct();
    std::unique_ptr<Bicycle> myMountainBike = director->GetResult();

    if (myMountainBike) {
        std::cout << "Bicycle built with Make: " << myMountainBike->Make << ", Model: " << myMountainBike->Model << std::endl;
    } else {
        std::cout << "Bicycle could not be built." << std::endl;
    }
}

Reference

  1. https://refactoring.guru/design-patterns/builder
  2. https://ianjustin39.github.io/ianlife/design-pattern/builder-pattern/
  3. https://en.wikipedia.org/wiki/Builder_pattern

上一篇
[Day 20] 將實作與抽象放在不同類別階層 — 橋接器模式 (Bridge Pattern)
下一篇
[Day 22] 為請求創建一條處理鍊 - 責任鍊設計模式 (Chain of Responsibility Pattern)
系列文
深入淺出設計模式 - 使用 C++37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言