1.Builder模式介紹
Bulider模式是一步一步創建一個複雜對象的創建一個複雜的創建型模式,它允許用戶在不知道內部構建細節的情況下,可以更精細地控制對象的構造流程。該模式是爲了將構建複雜對象的過程和它的部件解耦,使得構建過程和部件的表示隔離開來。
因爲一個複雜的對象有很多大量組成部分,如汽車,有車輪、方向盤、發動機,還有各種小零件等,如何將這些部分裝配成一輛汽車,這個裝配過程很漫長,也很複雜,對於這種情況,爲了在構建過程中對外部隱藏實現細節,就可以使用Biulder模式將部件和組裝過程分離,使得構建過程和部件都可以自由擴展,兩者之間的耦合也降到最低。
2.Builder模式的定義
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
3.Builder模式的使用場景
- 相同的方法,不同的執行順序,產生不同的事件結果時;
- 多個部件或零件,都可以裝配到一個對象中,但是產生的運行結果又不相同時。
- 產品類非常複雜,或者產品類中的調用順序不同產生了不同的作用,這個時候使用建造者模式非常合適。
- 當初始化一個對象特別複雜,如參數多,且很多參數都具有默認值時。
4.Builder模式的UMl類圖
角色介紹:
- Product產品類:產品的抽象類(一般來說,一個系統終會有多於一個產品類,而且這些產品類並不一定有共同的接口,而完全可以是不相關);
- Builder:抽象Builder類,規範產品的組建,一般是由子類實現具體的組建過程(一般而言,以接口獨立於應用程序的商業邏輯。模式中直接創建產品對象的是具體的建造者< ConcreteBuilder >角色。具體建造者類必須實現這個接口所要求的兩種方法:一種是建造方法;另一種是結果返還方法。一般來說,產品所包含的部件數目與建造方法的數目相符。換言之,有多少部件,就有多少相應的建造方法);
- ConcreteBuilder:具體的Builder類(擔任這個角色的是與應用程序緊密相關的一些類,它們在應用程序調用下創建產品的實例。這個角色要完成的任務包括:實現抽象建造者Builder所聲明的接口,給出一步一步地完成創建產品實例的操作。在創建過程完成後,提供產品的實例);
- Director:統一組裝過程(擔任這個角色的類調用具體建造者角色以創建產品對象。導演者角色並沒有產品類的具體知識,真正擁有產品類的具體知識的是具體建造者角色)。
5.Builder模式的簡單實現
計算機的組裝過程較爲複雜,並且組裝順序是不固定的,爲了易於理解,我們把計算機組裝的過程簡化爲構建主機、設置操作系統、設置顯示器3個部分,然後通過Director和具體的Builder來構建計算機對象。請看下看的示例:
//計算機抽象類
public abstract class Computer {
protected String mBoard;
protected String mDisplay;
protected String mOS;
protected Computer() {
}
public void setBoard(String board) {
this.mBoard = board;
}
public void setDisplay(String display) {
this.mDisplay = display;
}
public abstract void setOS();
@Override
public String toString() {
return "Computer [mBoard=" + mBoard + ",mDisplay=" + mDisplay + ",mOS="
+ mOS + "]";
}
}
具體的Computer類,Macbook
public class MacBook extends Computer {
@Override
public void setOS() {
mOS = "Mas OS X 10.10";
}
protected MacBook() {
}
}
//抽象Builder類
//抽象Builder類
public abstract class Builder {
// 設置主機
public abstract void buildBoard(String board);
// 設置顯示器
public abstract void buildDisplay(String display);
// 設置操作系統
public abstract void buildOS();
// 創建Computer
public abstract Computer create();
}
具體的Builder類,Macbookbuilder
public class MacbookBuilder extends Builder {
private Computer mComputer = new MacBook();
@Override
public void buildBoard(String board) {
mComputer.setBoard(board);
}
@Override
public void buildDisplay(String display) {
mComputer.setDisplay(display);
}
@Override
public void buildOS() {
mComputer.setOS();
}
@Override
public Computer create() {
return mComputer;
}
}
Director類,負責構造Computer
//Director類,負責構造Computer
public class Director {
Builder mBuilder = null;
public Director(Builder builder) {
this.mBuilder = builder;
}
public void construct(String board, String display) {
mBuilder.buildBoard(board);
mBuilder.buildDisplay(display);
mBuilder.buildOS();
}
}
測試代碼
public class Test {
public static void main(String[] args) {
// 構造器
Builder builder = new MacbookBuilder();
// Director
Director pcDirector = new Director(builder);
// 封裝構建過程,4核,內存2G、Mac系統
pcDirector.construct("英特爾主板", "Retina顯示器");
// 構建計算機,輸出相關信息
System.out.println("Computer Info:" + builder.create().toString());
}
}
輸出:
Computer Info:Computer [mBoard=英特爾主板,mDisplay=Retina顯示器,mOS=Mas OS X 10.10]
上述示例中,通過具體的MacbookBuilder來構建的Macbook對象,而Director封裝了構建複雜產品對象的過程,對外隱藏構建細節。Builder與Director一起將一個複雜的構建與它的表示分離,使得同樣的構建過程可以創建不同的對象。
值得注意的是,在現實開發中,Director角色經常會被省略。而直接使用一個Builder來進行對象的組裝,這個Builder通常爲鏈式調用,它的關鍵點是每個setter方法都返回自身,也就是return this,這樣就使得setter方法可以鏈式調用,代碼大致如下:
new TestBuilder.setA("A").setB("B").setC("C").create();
通過這種形式不僅去除了Director角色嗎整個結構也變簡單了,特能對Product對象的組裝過程有更精細的控制。
6.總結
Builder模式在Android開發中也較爲常用,
優點
- 良好的封裝性,使用建造者模式可以使客戶端不必知道產品內部組成的細節。
- 構建者獨立,容易擴展。
缺點 - 會產生多餘的Builder對象以及Director對象,消耗內存。
——摘錄《Android 源碼設計模式解析與實戰 第三章》