網站首頁 編程語言 正文
一、動機(Motivation)
在軟件系統中,有時候面臨著“一個復雜對象”的創建工作,其通常由各個部分的子對象用一定的算法構成;由于需求的變化,這個復雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的算法卻相對穩定。
如何應對這種變化?如何提供一種“封裝機制”來隔離出“復雜對象的各個部分”的變化,從而保持系統中的“穩定構建算法”不隨著需求改變而改變?
二、意圖(Intent)
將一個復雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。——《設計模式》GoF
三、結構(Structure)
協作(Collaborations)
四、模式的組成
(1)、抽象建造者角色(Builder):為創建一個Product對象的各個部件指定抽象接口,以規范產品對象的各個組成成分的建造。一般而言,此角色規定要實現復雜對象的哪些部分的創建,并不涉及具體的對象部件的創建。
(2)、具體建造者(ConcreteBuilder)
? ? ?1)實現Builder的接口以構造和裝配該產品的各個部件。即實現抽象建造者角色Builder的方法。
???? 2)定義并明確它所創建的表示,即針對不同的商業邏輯,具體化復雜對象的各部分的創建
???? 3) 提供一個檢索產品的接口
???? 4) 構造一個使用Builder接口的對象即在指導者的調用下創建產品實例
(3)、指導者(Director):調用具體建造者角色以創建產品對象的各個部分。指導者并沒有涉及具體產品類的信息,真正擁有具體產品的信息是具體建造者對象。它只負責保證對象各部分完整創建或按某種順序創建。
(4)、產品角色(Product):建造中的復雜對象。它要包含那些定義組件的類,包括將這些組件裝配成產品的接口。
五、建筑者模式的具體實現
現在人們的生活水平都提高了,有錢了,我今天就以汽車組裝為例子。每臺汽車的組裝過程都是一致的,所以我們使用同樣的構建過程可以創建不同的表示(即可以組裝成不同型號的汽車,不能像例子這樣,一會別克,一會奧迪的)
組裝汽車、電腦、手機、電視等等負責對象的這些場景都可以應用建造者模式來設計。
static void Main(string[] args)
{
Director director = new Director();
Builder buickCarBuilder = new BuickBuilder();
Builder aoDiCarBuilder = new AoDiBuilder();
director.Construct(buickCarBuilder);
Car buickCar = buickCarBuilder.GetCar(); //組裝完成,我來駕駛別克了
buickCar.Show();
director.Construct(aoDiCarBuilder); // 我老婆就要奧迪了,她比較喜歡大品牌
Car aoDiCar = aoDiCarBuilder.GetCar();
aoDiCar.Show();
}
/// <summary>
/// 這個類型才是組裝的,Construct方法里面的實現就是創建復雜對象固定算法的實現,該算法是固定的,或者說是相對穩定的
/// 這個人當然就是老板了,也就是建造者模式中的指揮者
/// </summary>
public class Director
{
// 組裝汽車
public void Construct(Builder builder)
{
builder.BuildCarDoor();
builder.BuildCarWheel();
builder.BuildCarEngine();
}
}
/// <summary>
/// 汽車類
/// </summary>
public sealed class Car
{
// 汽車部件集合
private IList<string> parts = new List<string>();
// 把單個部件添加到汽車部件集合中
public void Add(string part)
{
parts.Add(part);
}
public void Show()
{
Console.WriteLine("汽車開始在組裝.......");
foreach (string part in parts)
{
Console.WriteLine("組件" + part + "已裝好");
}
Console.WriteLine("汽車組裝好了");
}
}
/// <summary>
/// 抽象建造者,它定義了要創建什么部件和最后創建的結果,但是不是組裝的的類型,切記
/// </summary>
public abstract class Builder
{
// 創建車門
public abstract void BuildCarDoor();
// 創建車輪
public abstract void BuildCarWheel();
//創建車引擎
public abstract void BuildCarEngine();
// 獲得組裝好的汽車
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;
}
}
六、建造者模式的實現要點
在建造者模式中,指揮者是直接與客戶端打交道的,指揮者將客戶端創建產品的請求劃分為對各個部件的建造請求,再將這些請求委派到具體建造者角色,具體建造者角色是完成具體產品的構建工作的,卻不為客戶所知道。建造者模式主要用于“分步驟來構建一個復雜的對象”,其中“分步驟”是一個固定的組合過程,而復雜對象的各個部分是經常變化的。 產品不需要抽象類,由于建造模式的創建出來的最終產品可能差異很大,所以不大可能提煉出一個抽象產品類。
在前面文章中介紹的抽象工廠模式解決了“系列產品”的需求變化,而建造者模式解決的是?“產品部分”?的需要變化。
由于建造者隱藏了具體產品的組裝過程,所以要改變一個產品的內部表示,只需要再實現一個具體的建造者就可以了,從而能很好地應對產品組成組件的需求變化。
1、建造者模式的優點:
(1)、使用建造者模式可以使客戶端不必知道產品內部組成的細節。
(2)、具體的建造者類之間是相互獨立的,容易擴展。
(3)、由于具體的建造者是獨立的,因此可以對建造過程逐步細化,而不對其他的模塊產生任何影響。
2、建造者模式的缺點:
產生多余的Build對象以及Dirextor類。
3、創建者模式的使用場景:
(1)、當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時。
(2)、相同的方法,不同的執行順序,產生不同的事件結果時。
(3)、多個部件或零件,都可以裝配到一個對象中,但是產生的運行結果又不相同時。
(4)、產品類非常復雜,或者產品類中的調用順序不同產生了不同的效能。
(5)、創建一些復雜的對象時,這些對象的內部組成構件間的建造順序是穩定的,但是對象的內部組成構件面臨著復雜的變化。
七、.NET框架中的Builder應用
在ASP.Net中,我們在寫一個Page類時,這個類繼承自System.Web.UI.Page。Page其實就是一個Builder,它是一個容器。它有很多方法,就是所謂的BuilderPart()方法,例如:OnInit()、OnLoad()、OnPreRender()、Render()等,它們都是虛方法,我們都可以去重寫,提供我們自己的實現。當我們編譯到bin文件夾下的dll時,我們就生成了一個我們自己的ConcreteBuilder實例。實際上系統使用的是Page基類。
原文鏈接:https://www.cnblogs.com/springsnow/p/11303198.html
相關推薦
- 2022-09-28 基于OpenCV(python)的實現文本分割之垂直投影法_python
- 2023-05-09 C語言qsort函數用冒泡排序實現過程詳解_C 語言
- 2023-04-01 Unreal學習之簡單三角形的繪制詳解_C 語言
- 2023-04-28 react如何獲取URL中參數_React
- 2023-04-27 c++中關于max_element()函數解讀_C 語言
- 2022-06-01 C語言?深入淺出講解指針的使用_C 語言
- 2022-11-24 C++?OpenCV實現boxfilter方框濾波的方法詳解_C 語言
- 2022-07-30 react擴展6_renderProps
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支