建造者模式(Builder Pattern)
使用多個簡單的對象一步一步構建成一個複雜的對象。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
意圖:
將一個複雜的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。
主要解決:
主要解決在軟件系統中,有時候面臨着"一個複雜對象"的創建工作,其通常由各個部分的子對象用一定的算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨着劇烈的變化,但是將它們組合在一起的算法卻相對穩定。
何時使用:
一些基本部件不會變,而其組合經常變化的時候。
如何解決:
將變與不變分離開。
關鍵代碼:
建造者(Builder):創建和提供實例,指揮者(Director):控制產品的構建過程和組裝產品。
優點:
1、易於解耦 將產品本身與產品創建過程進行解耦,可以使用相同的創建過程來得到不同的產品。也就說細節依賴抽象。
2、易於精確控制對象的創建 將複雜產品的創建步驟分解在不同的方法中,使得創建過程更加清晰 3、易於拓展
增加新的具體建造者無需修改原有類庫的代碼,易於拓展,符合“開閉原則“。
每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產品對象。
缺點:
1、建造者模式所創建的產品一般具有較多的共同點,其組成部分相似;如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
2、如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
使用場景:
1、需要生成的對象具有複雜的內部結構。
2、需要生成的對象內部屬性本身相互依賴。
注意事項:
與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。
模式原理
UML類圖 & 組成
模式講解:
1. 指揮者(Director)直接和客戶(Client)進行需求溝通;
2. 溝通後指揮者將客戶創建產品的需求劃分爲各個部件的建造請求(Builder);
3. 將各個部件的建造請求委派到具體的建造者(ConcreteBuilder);
4. 各個具體建造者負責進行產品部件的構建;
5. 最終構建成具體產品(Product)。
實例講解
接下來我用一個實例來對建造者模式進行更深一步的介紹。
a. 實例概況
- 背景:小成希望去電腦城買一臺組裝的臺式主機
- 過程:
- 電腦城老闆(Diretor)和小成(Client)進行需求溝通(買來打遊戲?學習?看片?)
- 瞭解需求後,電腦城老闆將小成需要的主機劃分爲各個部件(Builder)的建造請求(CPU、主板blabla)
- 指揮裝機人員(ConcreteBuilder)去構建組件;
- 將組件組裝起來成小成需要的電腦(Product)
b. 使用步驟
步驟1: 定義組裝的過程(Builder):組裝電腦的過程
public abstract class Builder {
//第一步:裝CPU
//聲明爲抽象方法,具體由子類實現
public abstract void BuildCPU();
//第二步:裝主板
//聲明爲抽象方法,具體由子類實現
public abstract void BuildMainboard();
//第三步:裝硬盤
//聲明爲抽象方法,具體由子類實現
public abstract void BuildHD();
//返回產品的方法:獲得組裝好的電腦
public abstract Computer GetComputer();
}
步驟2: 電腦城老闆委派任務給裝機人員(Director)
public class Director{
//指揮裝機人員組裝電腦
public void Construct(Builder builder){
builder. BuildCPU();
builder.BuildMainboard();
builder. BuildHD();
}
}
步驟3: 創建具體的建造者(ConcreteBuilder):裝機人員
//裝機人員1
public class ConcreteBuilder extend Builder{
//創建產品實例
Computer computer = new Computer();
//組裝產品
@Override
public void BuildCPU(){
computer.Add("組裝CPU")
}
@Override
public void BuildMainboard(){
computer.Add("組裝主板")
}
@Override
public void BuildHD(){
computer.Add("組裝主板")
}
//返回組裝成功的電腦
@Override
public Computer GetComputer(){
return computer
}
}
步驟4: 定義具體產品類(Product):電腦
public class Computer{
//電腦組件的集合
private List<String> parts = new ArrayList<String>();
//用於將組件組裝到電腦裏
public void Add(String part){
parts.add(part);
}
public void Show(){
for (int i = 0;i<parts.size();i++){
System.out.println(“組件”+parts.get(i)+“裝好了”);
}
System.out.println(“電腦組裝完成,請驗收”);
}
}
步驟5: 客戶端調用-小成到電腦城找老闆買電腦
public class Builder Pattern{
public static void main(String[] args){
//逛了很久終於發現一家合適的電腦店
//找到該店的老闆和裝機人員
Director director = new Director();
Builder builder = new ConcreteBuilder();
//溝通需求後,老闆叫裝機人員去裝電腦
director.Construct(builder);
//裝完後,組裝人員搬來組裝好的電腦
Computer computer = builder.GetComputer();
//組裝人員展示電腦給小成看
computer.Show();
}
}
結果輸出
組件CUP裝好了
組件主板裝好了
組件硬盤裝好了
電腦組裝完成,請驗收