天天看點

C#設計模式(5)——建造者模式(Builder Pattern)

  在軟體系統中,有時需要建立一個複雜對象,并且這個複雜對象由其各部分子對象通過一定的步驟組合而成。例如一個采購系統中,如果需要采購員去采購一批電腦時,在這個實際需求中,電腦就是一個複雜的對象,它是由CPU、主機闆、硬碟、顯示卡、機箱等組裝而成的,如果此時讓采購員一台一台電腦去組裝的話真是要累死采購員了,這裡就可以采用建造者模式來解決這個問題,我們可以把電腦的各個元件的組裝過程封裝到一個建造者類對象裡,建造者隻要負責返還給用戶端全部元件都建造完畢的産品對象就可以了。然而現實生活中也是如此的,如果公司要采購一批電腦,此時采購員不可能自己去買各個元件并把它們組織起來,此時采購員隻需要像電腦城的老闆說自己要采購什麼樣的電腦就可以了,電腦城老闆自然會把組裝好的電腦送到公司。下面就以這個例子來展開建造者模式的介紹。

  在這個例子中,電腦城的老闆是直接與客戶(也就是指采購員)聯系的,然而電腦的組裝是由老闆指揮裝機人員去把電腦的各個部件組裝起來,真真負責建立産品(這裡産品指的就是電腦)的人就是電腦城的裝機人員。理清了這個邏輯過程之後,下面就具體看下如何用代碼來表示這種現實生活中的邏輯過程:

上面代碼中都有詳細的注釋代碼,這裡就不過多解釋,大家可以參考代碼和注釋來與現實生活中的例子做對比,下圖展示了上面代碼的運作結果:

C#設計模式(5)——建造者模式(Builder Pattern)

  介紹完了建造者模式的具體實作之後嗎,下面具體看下建造者模式的具體定義是怎樣的。

建造者模式(Builder Pattern):将一個複雜對象的建構于它的表示分離,使得同樣的建構過程可以建立不同的表示。

建造者模式使得建造代碼與表示代碼的分離,可以使用戶端不必知道産品内部組成的細節,進而降低了用戶端與具體産品之間的耦合度,下面通過類圖來幫助大家更好地理清建造者模式中類之間的關系。

C#設計模式(5)——建造者模式(Builder Pattern)

介紹完了建造者模式的具體實作之後,讓我們總結下建造模式的實作要點:

在建造者模式中,指揮者是直接與用戶端打交道的,指揮者将用戶端建立産品的請求劃分為對各個部件的建造請求,再将這些請求委派到具體建造者角色,具體建造者角色是完成具體産品的建構工作的,卻不為客戶所知道。

建造者模式主要用于“分步驟來建構一個複雜的對象”,其中“分步驟”是一個固定的組合過程,而複雜對象的各個部分是經常變化的(也就是說電腦的内部元件是經常變化的,這裡指的的變化如硬碟的大小變了,CPU由單核變雙核等)。

産品不需要抽象類,由于建造模式的建立出來的最終産品可能差異很大,是以不大可能提煉出一個抽象産品類。

在前面文章中介紹的抽象工廠模式解決了“系列産品”的需求變化,而建造者模式解決的是 “産品部分” 的需要變化。

由于建造者隐藏了具體産品的組裝過程,是以要改變一個産品的内部表示,隻需要再實作一個具體的建造者就可以了,進而能很好地應對産品組成元件的需求變化。

  前面的設計模式在.NET類庫中都有相應的實作,那在.NET 類庫中,是否也存在建造者模式的實作呢? 然而對于疑問的答案是肯定的,在.NET 類庫中,System.Text.StringBuilder(存在mscorlib.dll程式集中)就是一個建造者模式的實作。不過它的實作屬于建造者模式的演化,此時的建造者模式沒有指揮者角色和抽象建造者角色,StringBuilder類即扮演着具體建造者的角色,也同時扮演了指揮者和抽象建造者的角色,此時建造模式的實作如下:

  StringBuilder類扮演着建造string對象的具體建造者角色,其中的ToString()方法用來傳回具體産品給用戶端(相當于上面代碼中GetProduct方法)。其中Append方法用來建立産品的元件(相當于上面代碼中BuildPartA和BuildPartB方法),因為string對象中每個元件都是字元,是以也就不需要指揮者的角色的代碼(指的是Construct方法,用來調用建立每個元件的方法來完成整個産品的組裝),因為string字元串對象中每個元件都是一樣的,都是字元,是以Append方法也充當了指揮者Construct方法的作用。

  到這裡,建造者模式的介紹就結束了,建造者模式(Builder Pattern),将一個複雜對象的建構與它的表示分離,使的同樣的建構過程可以建立不同的表示。建造者模式的本質是使組裝過程(用指揮者類進行封裝,進而達到解耦的目的)和建立具體産品解耦,使我們不用去關心每個元件是如何組裝的。

繼續閱讀