?動機(Motivation)
?1、在軟件系統中,有時候面臨著“一個復雜對象”的創建工作,其通常由各個部分的子對象用一定的算法構成;由于需求的變化,這個復雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的算法卻相對穩定。
2、如何應對這種變化?如何提供一種“封裝機制”來隔離出“復雜對象的各個部分”的變化,從而保持系統中的“穩定構建算法”不隨著需求改變而改變?
?基本概念
定義:構建器模式是一種創建型設計模式,它允許您分步驟創建復雜對象,使得相同的構建過程可以創建不同的表示。
構建器模式的核心思想是將復雜對象的構建與其表示分離,使得:
客戶端不需要知道對象內部的具體組成細節
相同的構建過程可以創建不同的表示
可以更精細地控制對象的構建過程
實現方式
1. 經典構建器模式實現
#include <iostream>
#include <memory>
#include <string>// 最終要構建的產品
class Pizza {
public:void setDough(const std::string& dough) {dough_ = dough;}void setSauce(const std::string& sauce) {sauce_ = sauce;}void setTopping(const std::string& topping) {topping_ = topping;}void showPizza() const {std::cout << "Pizza with " << dough_ << " dough, "<< sauce_ << " sauce and "<< topping_ << " topping." << std::endl;}private:std::string dough_;std::string sauce_;std::string topping_;
};// 抽象構建器
class PizzaBuilder {
public:virtual ~PizzaBuilder() = default;Pizza* getPizza() {return pizza_.get();}void createNewPizza() {pizza_ = std::make_unique<Pizza>();}virtual void buildDough() = 0;virtual void buildSauce() = 0;virtual void buildTopping() = 0;protected:std::unique_ptr<Pizza> pizza_;
};// 具體構建器 - HawaiianPizzaBuilder
class HawaiianPizzaBuilder : public PizzaBuilder {
public:void buildDough() override {pizza_->setDough("cross");}void buildSauce() override {pizza_->setSauce("mild");}void buildTopping() override {pizza_->setTopping("ham+pineapple");}
};// 具體構建器 - SpicyPizzaBuilder
class SpicyPizzaBuilder : public PizzaBuilder {
public:void buildDough() override {pizza_->setDough("pan baked");}void buildSauce() override {pizza_->setSauce("hot");}void buildTopping() override {pizza_->setTopping("pepperoni+salami");}
};// 指導者 (Director) - 控制構建過程
class Cook {
public:void setPizzaBuilder(PizzaBuilder* pb) {pizzaBuilder_ = pb;}Pizza* getPizza() {return pizzaBuilder_->getPizza();}void constructPizza() {pizzaBuilder_->createNewPizza();pizzaBuilder_->buildDough();pizzaBuilder_->buildSauce();pizzaBuilder_->buildTopping();}private:PizzaBuilder* pizzaBuilder_;
};int main() {Cook cook;// 構建 Hawaiian PizzaHawaiianPizzaBuilder hawaiianBuilder;cook.setPizzaBuilder(&hawaiianBuilder);cook.constructPizza();Pizza* hawaiianPizza = cook.getPizza();hawaiianPizza->showPizza(); // 輸出: Pizza with cross dough, mild sauce and ham+pineapple topping.// 構建 Spicy PizzaSpicyPizzaBuilder spicyBuilder;cook.setPizzaBuilder(&spicyBuilder);cook.constructPizza();Pizza* spicyPizza = cook.getPizza();spicyPizza->showPizza(); // 輸出: Pizza with pan baked dough, hot sauce and pepperoni+salami topping.return 0;
}
2. 流式接口構建器 (更現代的C++實現)
#include <iostream>
#include <memory>
#include <string>class Computer {
public:void setCPU(const std::string& cpu) { cpu_ = cpu; }void setRAM(const std::string& ram) { ram_ = ram; }void setStorage(const std::string& storage) { storage_ = storage; }void setGPU(const std::string& gpu) { gpu_ = gpu; }void showSpecs() const {std::cout << "Computer Specs:\n"<< "CPU: " << cpu_ << "\n"<< "RAM: " << ram_ << "\n"<< "Storage: " << storage_ << "\n"<< "GPU: " << (gpu_.empty() ? "Integrated" : gpu_) << "\n";}private:std::string cpu_;std::string ram_;std::string storage_;std::string gpu_;
};class ComputerBuilder {
public:ComputerBuilder() : computer_(std::make_unique<Computer>()) {}ComputerBuilder& setCPU(const std::string& cpu) {computer_->setCPU(cpu);return *this;}ComputerBuilder& setRAM(const std::string& ram) {computer_->setRAM(ram);return *this;}ComputerBuilder& setStorage(const std::string& storage) {computer_->setStorage(storage);return *this;}ComputerBuilder& setGPU(const std::string& gpu) {computer_->setGPU(gpu);return *this;}std::unique_ptr<Computer> build() {return std::move(computer_);}private:std::unique_ptr<Computer> computer_;
};int main() {// 使用流式接口構建計算機auto gamingPC = ComputerBuilder().setCPU("Intel i9-13900K").setRAM("32GB DDR5").setStorage("2TB NVMe SSD").setGPU("NVIDIA RTX 4090").build();gamingPC->showSpecs();auto officePC = ComputerBuilder().setCPU("AMD Ryzen 5").setRAM("16GB DDR4").setStorage("512GB SSD").build(); // 沒有設置GPUofficePC->showSpecs();return 0;
}
?UML結構
?
構建器模式的優點
分步構建:可以分步驟構建復雜對象
復用構建過程:相同的構建過程可以創建不同的產品
單一職責原則:將復雜對象的構建代碼與其業務邏輯分離
更好的控制:對構建過程有更精細的控制
可擴展性:添加新的具體構建器無需修改現有代碼
適用場景
當創建復雜對象的算法應該獨立于該對象的組成部分及其裝配方式時
當構造過程必須允許被構造的對象有不同的表示時
當需要避免"伸縮構造函數"問題(構造函數參數過多)時
當對象有大量可選組件或配置時
構建器模式的變體
流式接口構建器:通過方法鏈提供更優雅的API
Groovy風格構建器:利用C++運算符重載實現更自然的語法
組合構建器:多個構建器協同工作構建復雜對象
注意事項
構建器模式會增加代碼復雜度,因為需要創建多個新類
對于簡單對象,直接使用構造函數可能更合適
確保構建器在構建完成后不能被重復使用(除非顯式重置)
構建器模式在C++中特別適合用于創建配置復雜的對象,特別是當對象有許多可選組件時。流式接口的實現方式使得代碼更加清晰易讀。