一、定義
GOF定義:將一個複雜對象的構造與它的表示分離,使同樣的構建過程可以創建不同的表示,這樣的設計模式被稱爲建造者模式。
Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23種設計模式中的一種。Builder模式是一種對象創建型模式之一,用來隱藏複合對象的創建過程,它把複合對象的創建過程加以抽象,通過子類繼承和重載的方式,動態地創建具有複合屬性的對象。
例如,計算機是由 OPU、主板、內存、硬盤、顯卡、機箱、顯示器、鍵盤、鼠標等部件組裝而成的,採購員不可能自己去組裝計算機,而是將計算機的配置要求告訴計算機銷售公司,計算機銷售公司安排技術人員去組裝計算機,然後再交給要買計算機的採購員。
這些產品都是由多個部件構成的,各個部件可以靈活選擇,但其創建步驟都大同小異,即產品的組成部分是不變的,但每一部分是可以靈活選擇的。這類產品的創建無法用前面介紹的工廠模式描述,只有建造者模式可以很好地描述該類產品的創建。
二、角色
1.建造者(Builder):
爲創建一個產品對象的各個部件指定抽象接口。
2.具體建造者(ConcreteBuilder):
實現Builder的接口以構造和裝配該產品的各個部件,定義並明確它所創建的表示,並提供一個檢索產品的接口。
3.指揮者(Director):
指揮並構造一個使用Builder接口的對象。
4. 產品(Product):
表示被構造的複雜對象。ConcreteBuilder創建該產品的內部表示並定義它的裝配過程,包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。
ConcreteBuilder創建該產品的內部表示並定義它的裝配過程,包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。
UML類圖如下:
三、實現
#include<iostream>
using namespace std;
//具體產品,房子,由門、窗、牆等組成。
class House{
private:
string m_door;
string m_window;
string m_wall;
public:
void setDoor(string door){
this->m_door = door;
}
void setWindow(string window){
this->m_window = window;
}
void setWall(string wall){
this->m_wall = wall;
}
string getDoor(){
cout<<this->m_door.c_str()<<endl;
return this->m_door;
}
string getWindow(){
cout<<this->m_window.c_str()<<endl;
return this->m_window;
}
string getWall(){
cout<<this->m_wall.c_str()<<endl;
return this->m_wall;
}
};
//Builder,提供構建房子各個組件的接口
class Builder{
public:
virtual void builderDoor() = 0;
virtual void builderWindow() = 0 ;
virtual void builderWall() = 0 ;
virtual House* getHouse() = 0 ;
};
//指揮者,調用具體建造者構造具體的產品,和用戶直接交互,使用戶不用具體知道產品的實現細節。
class Director{
public:
Director(){
}
void construct(Builder *builder){
builder->builderDoor();
builder->builderWindow();
builder->builderWall();
}
};
//具體建造者,對對象各部件進行設置
//建造公寓
class FlatBuilder:public Builder{
private:
House* m_house;
public:
FlatBuilder(){
this->m_house = new House;
}
void builderDoor(){
this->m_house->setDoor("flat door");
}
void builderWindow(){
this->m_house->setWindow("flat window");
}
void builderWall(){
this->m_house->setWall("flat wall");
}
House* getHouse(){
return this->m_house;
}
};
//建造別墅
class VillaBuilder:public Builder{
private:
House* m_house;
public:
VillaBuilder(){
this->m_house = new House;
}
void builderDoor(){
this->m_house->setDoor("valli door");
}
void builderWindow(){
this->m_house->setWindow("valli window");
}
void builderWall(){
this->m_house->setWall("valli wall");
}
House* getHouse(){
return this->m_house;
}
};
int main(){
House *house = nullptr;
Builder *builder = nullptr;
Director *director = nullptr;
//創建指揮者
director = new Director();
//client將建造房子的是交給指揮者,完全不用知曉怎樣建造
builder = new FlatBuilder();
director->construct(builder);
//建造好,交付房子
house = builder->getHouse();
house->getDoor();
house->getWindow();
house->getWall();
delete house;
delete builder;
builder = new VillaBuilder();
director->construct(builder);
house = builder->getHouse();
house->getDoor();
house->getWindow();
house->getWall();
delete house;
delete builder;
delete director;
return 0 ;
}
四、優缺點
主要優點如下:
各個具體的建造者相互獨立,有利於系統的擴展。
客戶端不必知道產品內部組成的細節,便於控制細節風險。
缺點如下:
產品的組成部分必須相同,這限制了其使用範圍。
如果產品的內部變化複雜,該模式會增加很多的建造者類。
五、建造者模式與工廠模式的區別
Factory模式:
1、有一個抽象的工廠。
2、實現一個具體的工廠—汽車工廠。
3、A工廠生產汽車A,得到汽車產品A。
4、B工廠生產汽車B,得到汽車產品B。
這樣做,實現了購買者和生產線的隔離。強調的是結果。
Builder模式:
1、引擎工廠生產引擎產品,得到汽車部件A。
2、輪胎工廠生產輪子產品,得到汽車部件B。
3、底盤工廠生產車身產品,得到汽車部件C。
4、將這些部件放到一起,形成剛好能夠組裝成一輛汽車的整體。
5、將這個整體送到汽車組裝工廠,得到一個汽車產品。
這樣做,目的是爲了實現複雜對象生產線和其部件的解耦。強調的是過程
兩者的區別在於:
Factory模式不考慮對象的組裝過程,而直接生成一個我想要的對象。
Builder模式先一個個的創建對象的每一個部件,再統一組裝成一個對象。
Factory模式所解決的問題是,工廠生產產品。
而Builder模式所解決的問題是工廠控制產品生成器組裝各個部件的過程,然後從產品生成器中得到產品。
六、應用場景
建造者(Builder)模式創建的是複雜對象,其產品的各個部分經常面臨着劇烈的變化,但將它們組合在一起的算法卻相對穩定,所以它通常在以下場合使用。
創建的對象較複雜,由多個部件構成,各部件面臨着複雜的變化,但構件間的建造順序是穩定的。創建複雜對象的算法獨立於該對象的組成部分以及它們的裝配方式,即產品的構建過程和最終的表示是獨立的。