設計模式解密(6) - 建造者模式
1、簡介
定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
英文:Builder
類型:創建類模式
2、原理及組成
引:類圖
四個要素
- 產品類:一般是一個較為復雜的對象,也就是說創建對象的過程比較復雜,一般會有比較多的代碼量。在本類圖中,產品類是一個具體的類,而非抽象類。實際編程中,產品類可以是由一個抽象類與它的不同實現組成,也可以是由多個抽象類與他們的實現組成。
- 抽象建造者:引入抽象建造者的目的,是為了將建造的具體過程交與它的子類來實現。這樣更容易擴展。一般至少會有兩個抽象方法,一個用來建造產品,一個是用來返回產品。
- 建造者:實現抽象類的所有未實現的方法,具體來說一般是兩項任務:組建產品;返回組建好的產品。
- 導演類:負責調用適當的建造者來組建產品,導演類一般不與產品類發生依賴關系,與導演類直接交互的是建造者類。一般來說,導演類被用來封裝程序中易變的部分。
3、實例引入
背景:模擬生產各種筆(這裏假設筆的零件生產是有順序的:筆芯 -> 筆殼 -> 組裝)
創建抽象產品類 -- 筆
package com.designpattern.builder; /** * 筆 -- 抽象產品類 */ public abstract class Pen { /**筆芯**/ private String cartridge; /**外殼**/ private String shell; public String getCartridge() { return cartridge; } public void setCartridge(String cartridge) { this.cartridge = cartridge; } public String getShell() { return shell; } public void setShell(String shell) { this.shell = shell; } }
創建抽象建造者(筆builder) 接口
package com.designpattern.builder; /** * 抽象建造者 -- 筆builder */ public abstract interface PenBuilder { /** * 生產筆芯 */ abstract void buildCartridge(); /** * 生產外殼 */ abstract void buildShell(); /** * 組裝筆 */ abstract Pen buildPen(); }
創建具體產品類(圓珠筆)
package com.designpattern.builder; /** * 具體產品類 -- 圓珠筆 */ public class BallpointPen extends Pen{ public BallpointPen(){ System.out.println("生產組裝圓珠筆"); } }
創建具體產品類(畫筆)
package com.designpattern.builder; /** * 具體產品類 -- 畫筆 */ public class BrushPen extends Pen{ public BrushPen(){ System.out.println("生產組裝畫筆"); } }
創建建造者(具體) -- 圓珠筆builder
package com.designpattern.builder.impl; import com.designpattern.builder.BallpointPen; import com.designpattern.builder.Pen; import com.designpattern.builder.PenBuilder; /** * 建造者(具體) -- 圓珠筆builder */ public class BallpointPenBuilder implements PenBuilder{ Pen pen; public BallpointPenBuilder(){ pen = new BallpointPen(); } @Override public void buildCartridge() { pen.setCartridge("圓珠筆筆芯"); } @Override public void buildShell() { pen.setShell("圓珠筆外殼"); } @Override public Pen buildPen() { return pen; } }
創建建造者(具體) -- 畫筆builder
package com.designpattern.builder.impl; import com.designpattern.builder.BrushPen; import com.designpattern.builder.Pen; import com.designpattern.builder.PenBuilder; /** * 建造者(具體) -- 畫筆builder */ public class BrushPenBuilder implements PenBuilder{ Pen pen; public BrushPenBuilder(){ pen = new BrushPen(); } @Override public void buildCartridge() { pen.setCartridge("畫筆筆芯"); } @Override public void buildShell() { pen.setShell("畫筆外殼"); } @Override public Pen buildPen() { return pen; } }
創建導演類 Director
package com.designpattern.builder; /** * 導演類 Director */ public class PenDirector { public Pen constructPen(PenBuilder pen_builder){ //生產筆芯 pen_builder.buildCartridge(); //生產外殼 pen_builder.buildShell(); //組裝筆 return pen_builder.buildPen(); } }
下面測試一下
package com.designpattern.builder; import com.designpattern.builder.impl.BallpointPenBuilder; import com.designpattern.builder.impl.BrushPenBuilder; /** * 測試 */ public class Test { public static void main(String[] args) { PenDirector director = new PenDirector(); Pen ballpointpen = director.constructPen(new BallpointPenBuilder()); Pen brushpen = director.constructPen(new BrushPenBuilder()); } }
結果:
生產組裝圓珠筆 生產組裝畫筆
4、解決的問題
筆的種類不止這幾種,還有很多,使用建造者模式可以將一類產品的構建過程和細節進行封裝(實現代碼的復用)與產品的表示進行分離,即:使用同樣的構建過程可以創建不同的產品;
在各個建造者類,只需定義生產零件方法,具體的生產順序定義在導演類中;
5、優缺點
優點:
(封裝性)建造者模式的封裝性很好。使用建造者模式可以有效的封裝變化,在使用建造者模式的場景中,一般產品類和建造者類是比較穩定的,因此,將主要的業務邏輯封裝在導演類中對整體而言可以取得比較好的穩定性。
(擴展性)建造者模式很容易進行擴展。如果有新的需求,通過實現一個新的建造者類就可以完成,基本上不用修改之前已經測試通過的代碼,因此也就不會對原有功能引入風險。
(便於控制細節風險)由於具體的建造者是獨立的,因此可以對建造者過程逐步細化,而不對其他的模塊產生任何影響。
缺點:
建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
如果產品的內部變化復雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
6、應用場景
建造者模式 --- 建造具有具體細節的產品
1、需要生成的產品對象有復雜的內部結構,這些產品對象具備共性。
2、需要生成的產品對象的屬性相互依賴,建造者模式可以強迫生成順序。
........
7、與其他模式對比
我們可以看到,建造者模式與工廠模式是極為相似的,總體上,建造者模式僅僅只比工廠模式多了一個“導演類”的角色。在建造者模式的類圖中,假如把這個導演類看做是最終調用的客戶端,那麽圖中剩余的部分就可以看作是一個簡單的工廠模式了。
這裏先回歸一下定義:
工廠模式:定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類;
建造者模式:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示;
與工廠模式相比,建造者模式一般用來創建更為復雜的對象,因為對象的創建過程更為復雜,因此將對象的創建過程獨立出來組成一個新的類——導演類。也就是說,工廠模式是將對象的全部創建過程封裝在工廠類中,由工廠類向客戶端提供最終的產品;而建造者模式中,建造者類一般只提供產品類中各個組件的建造,而將具體建造過程交付給導演類。由導演類負責將各個組件按照特定的規則組建為產品,然後將組建好的產品交付給客戶端。
工廠模式一般都是創建一個產品,註重的是把這個產品創建出來就行,只要創建出來,不關心這個產品的組成部分。
建造者模式也是創建一個產品,但是不僅要把這個產品創建出來,還要關心這個產品的組成細節, 組成過程。
8、總結
建造者模式最主要功能是基本方法的調用順序安排,也就是這些基本方法已經實現了;
而工廠方法則重點是創建,你要什麽對象就創造一個對象出來,組裝順序則不是他關心的。
PS:建造模式的關鍵是導演角色,這個角色掌握了零件對象的狀態和產品的整體組裝藍圖。沒有了這個角色,建造模式就不是建造模式。當然,導演角色可以同時持有很多種藍圖,按照需要給出完全不同的組裝結果。
PS2:源碼地址 https://github.com/JsonShare/DesignPattern/tree/master
設計模式解密(6) - 建造者模式