## 前言 在軟體系統中,有時候面臨著“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的演算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中 ...
前言
在軟體系統中,有時候面臨著“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的演算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中的“穩定構建演算法”不隨著需求改變而改變?那就是今天分享的建造者模式,又叫生成器模式,英文名稱是Builder Pattern。
建造者模式定義
在現實生活中,我們經常會遇到一些構成比較複雜的物品,比如:汽車、電腦和手機等等。它們是一個複雜的物品,主要是由各種零部件組裝而成的,他們的組裝過程是固定的。就拿汽車來說,組裝流水線是固定的,不變的,需要把底盤、車輪、車門、車燈、發動機引擎、車燈和排氣筒等等組裝在一起。但是由於需求的變化,這個汽車複雜對象針對不同的品牌,各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。建造者設計模式定義就是將一個複雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。
建造者模式組成
(1)抽象建造者角色(Builder):為創建一個Product對象的各個部件指定抽象介面,以規範產品對象的各個組成成分的建造。一般而言,此角色規定要實現複雜對象的哪些部分的創建,並不涉及具體的對象部件的創建。
(2)具體建造者(ConcreteBuilder)
- 實現Builder的介面以構造和裝配該產品的各個部件。即實現抽象建造者角色Builder的方法。
- 定義並明確它所創建的表示,即針對不同的商業邏輯,具體化複雜對象的各部分的創建。
- 提供一個檢索產品的介面。
- 構造一個使用Builder介面的對象即在指導者的調用下創建產品實例。
(3)指導者(Director):調用具體建造者角色以創建產品對象的各個部分。指導者並沒有涉及具體產品類的信息,真正擁有具體產品的信息是具體建造者對象。它只負責保證對象各部分完整創建或按某種順序創建。
(4)產品角色(Product):建造中的複雜對象,對應具體的產品。它要包含那些定義組件的類,包括將這些組件裝配成產品的介面。
建造者模式代碼實現
抽象建造者
/// <summary>
/// 抽象建造者,它定義了要創建什麼部件和最後創建的結果,但是不是組裝的的類型
/// </summary>
public abstract class Builder
{
/// <summary>
/// 創建車門
/// </summary>
public abstract void BuildCarDoor();
/// <summary>
/// 創建車輪
/// </summary>
public abstract void BuildCarWheel();
/// <summary>
/// 創建車引擎
/// </summary>
public abstract void BuildCarEngine();
/*
* 當然還有部件:
* 大燈
* 地盤
* ....
* ....
*/
/// <summary>
/// 獲得組裝完成的汽車
/// </summary>
/// <returns></returns>
public abstract Car GetCar();
}
具體建造者
別克:
/// <summary>
/// 具體建造者,具體的車型的建造者,例如:別克
/// </summary>
public sealed class BuickBuilder : Builder
{
Car buickCar = new Car("別克");
public override void BuildCarDoor()
{
buickCar.Add("Buick's Door");
}
public override void BuildCarWheel()
{
buickCar.Add("Buick's Wheel");
}
public override void BuildCarEngine()
{
buickCar.Add("Buick's Engine");
}
public override Car GetCar()
{
return buickCar;
}
}
奧迪:
/// <summary>
/// 具體建造者,具體的車型的建造者,例如:奧迪
/// </summary>
public sealed class AoDiBuilder : Builder
{
Car aoDiCar = new Car("奧迪");
public override void BuildCarDoor()
{
aoDiCar.Add("Aodi's Door");
}
public override void BuildCarWheel()
{
aoDiCar.Add("Aodi's Wheel");
}
public override void BuildCarEngine()
{
aoDiCar.Add("Aodi's Engine");
}
public override Car GetCar()
{
return aoDiCar;
}
}
汽車固定組裝流程定義
/// <summary>
/// 汽車類
/// </summary>
public sealed class Car
{
// 汽車部件集合
private IList<string> parts = new List<string>();
//汽車品牌名
private string _brandName;
/// <summary>
/// 構造函數
/// </summary>
/// <param name="brandName"></param>
public Car(string brandName)
{
_brandName = brandName;
}
/// <summary>
/// 把單個部件添加到汽車部件集合中
/// </summary>
/// <param name="part"></param>
public void Add(string part)
{
parts.Add(part);
}
/// <summary>
/// 汽車組裝流程
/// </summary>
public void Assembly()
{
Console.WriteLine($"{_brandName}汽車開始在組裝.......");
foreach (string part in parts)
{
Console.WriteLine("組件" + part + "已裝好...");
}
Console.WriteLine($"{_brandName}汽車組裝完畢.........");
}
}
指導者
這裡才是調用組裝的,Construct方法裡面的實現就是創建複雜對象固定演算法的實現,根據具體需求變化,控制組裝的流程順序,該演算法是固定的,或者說是相對穩定的。
/// <summary>
/// 自動化工廠操控台,也就是建造者模式中的指揮者
/// </summary>
public class Director
{
/// <summary>
/// 自動化演算法指導組裝汽車
/// </summary>
/// <param name="builder"></param>
public void Construct(Builder builder)
{
builder.BuildCarDoor();
builder.BuildCarWheel();
builder.BuildCarEngine();
/*
* 指導其他流程
*/
}
}
調用
/// <summary>
/// 測試方法
/// </summary>
public void RunTest()
{
Director director = new Director();
//組裝別克
Builder buickCarBuilder = new BuickBuilder();
director.Construct(buickCarBuilder);
Car buickCar = buickCarBuilder.GetCar();
buickCar.Assembly();
Console.WriteLine("\r\n*****************************\r\n");
//組裝奧迪
Builder aoDiCarBuilder = new AoDiBuilder();
director.Construct(aoDiCarBuilder);
Car aoDiCar = aoDiCarBuilder.GetCar();
aoDiCar.Assembly();
}
建造者模式優缺點
優點:
-
使用建造者模式可以使客戶端不必知道產品內部組成的細節。
-
具體的建造者類之間是相互獨立的,容易擴展。
-
由於具體的建造者是獨立的,因此可以對建造過程逐步細化,而不對其他的模塊產生任何影響。
缺點:
- 產生多餘的Build對象以及Director類。
本文來自博客園,作者:碼農阿亮,轉載請註明原文鏈接:https://www.cnblogs.com/wml-it/p/17665000.html
技術的發展日新月異,隨著時間推移,無法保證本博客所有內容的正確性。如有誤導,請大家見諒,歡迎評論區指正!
開源庫地址,歡迎點亮:
GitHub:https://github.com/ITMingliang
Gitee: https://gitee.com/mingliang_it
GitLab: https://gitlab.com/ITMingliang
建群聲明: 本著技術在於分享,方便大家交流學習的初心,特此建立【編程內功修煉交流群】,為大家答疑解惑。熱烈歡迎各位愛交流學習的程式員進群,也希望進群的大佬能不吝分享自己遇到的技術問題和學習心得!進群方式:掃碼關註公眾號,後臺回覆【進群】。