在未上大學之前,一直有個夢想“I have a dream!”,就是能成為一位汽車工程師,一直幻想著開著自己設計的汽車飛奔在公路上,迷倒了萬千少女。咳咳~~雖然現在沒實現我的dream,但夢想還是得有的。
說到建造者模式,汽車絕對是典型的列子。汽車本身就是複雜產品物件,其製造過程可以形象的表示建造者模式。
一、建造者模式
定義
將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
特點
1.在某些屬性沒有賦值之前,複雜物件不能作為一個完整的產品使用。比如汽車包括方向盤、車門、發動機等各部件,缺少了這些部件就不能生產使用。
2.物件的一些屬性必須按照順序賦值,比如汽車應有車架才能裝車輪和其他部件。
UML
從上面的UML可以看出,建造者模式涉及到以下四個角色的概念:
- 抽象建造者角色:提供一個介面,規範產品物件的建造,一般由子類實現。一般來說,產品的組成部分數與建造方法數相同,即有多少組成部分,就有多少個建造方法。
- 具體建造者角色:該角色實現了抽象建造者抽象建造者介面,主要是實現所有宣告的方法以及返回建造好的產品例項。
- 導演者角色:負責呼叫具體建造者按照順序建造產品。導演者只負責排程,真正執行的是具體建造者角色。
- 產品角色:該角色是建造的複雜物件,提供基本方法。
二、實戰
上程式碼
現在要做兩輛萬眾矚目的豪車,一輛蘭博基尼,fine。另一輛法拉利,ok。一起來看看怎麼造這兩臺車...
產品角色程式碼如下:
public class Production {
private String part1;
private String part2;
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}複製程式碼
抽象建造者角色程式碼如下:
public interface IBuilder {
// 產品有多少個元件,就有多少個建造方法
public void buildPart1();
public void buildPart2();
// 返回產品類
public Production build();
}複製程式碼
首先來看蘭博基尼怎麼做,程式碼如下:
public class BuilderA implements IBuilder {
private Production production = new Production();
@Override
public void buildPart1() {
System.out.println("構造蘭博基尼的第一部分。");
production.setPart1("This is part1 of Lamborghini");
}
@Override
public void buildPart2() {
System.out.println("構造蘭博基尼的第二部分。");
production.setPart2("This is part2 of Lamborghini");
}
@Override
public Production build() {
System.out.println("咔擦!蘭博基尼已造好!");
return production;
}
}複製程式碼
導演者角色排程構建,程式碼如下:
public class Director {
private IBuilder builder;
public Director(IBuilder builder){
this.builder = builder;
}
/**
* 構造順序
*/
public Production construct(){
builder.buildPart1();
builder.buildPart2();
return builder.build();
}
}複製程式碼
下面看看客戶端如何使用建造者模式把蘭博基尼造出來,程式碼如下:
public class Client {
public static void main(String[] args){
// 蘭博基尼
IBuilder builderA = new BuilderA();
Director directorA = new Director(builderA);
directorA.construct();
}
}複製程式碼
執行客戶端程式碼,結果如下:
構造蘭博基尼的第一部分。
構造蘭博基尼的第二部分。
咔擦!蘭博基尼已造好!
接下來要造法拉利了,步驟一樣,先實現抽象建造者介面。
法拉利具體建造者程式碼如下:
public class BuilderB implements IBuilder {
private Production production = new Production();
@Override
public void buildPart1() {
System.out.println("構造法拉利的第一部分。");
production.setPart1("This is part1 of Ferrari");
}
@Override
public void buildPart2() {
System.out.println("構造法拉利的第二部分。");
production.setPart2("This is part2 of Ferrari");
}
@Override
public Production build() {
return production;
}
}複製程式碼
客戶端建造法拉利程式碼如下:
public class Client {
public static void main(String[] args) {
// 法拉利
IBuilder builderB = new BuilderB();
Director directorB = new Director(builderB);
directorB.construct();
}
}複製程式碼
客戶端執行結果如下:
構造法拉利的第一部分。
構造法拉利的第二部分。
咻咻!法拉利已造好!
三、建造者模式的優缺點
優點
1)降低程式碼耦合度。在建造者模式中,客戶端不需要知道產品內部是如何實現的,我們只需得到產品的物件。並且使用導演者和建造者分離組裝過程和元件具體構造過程,具有靈活的擴充套件性。
2)優秀的擴充套件性。具體建造者相互獨立,方便擴充套件,符合開閉原則。
缺點
1)一定的使用範圍限制。建造者模式的產品的元件基本相同,如果產品的差異性較大,建造者模式就不適用了。
四、比較
跟工廠方法模式對比:建造者模式和工廠模式同樣是建立一個產品,工廠模式就是一個方法,而建造者模式有多個方法,並且建造者模式是有順序的執行方法。就是說建造者模式強調的是順序,而工廠模式沒有順序一說。
總結
好了,蘭博基尼和法拉利的都擁有了,體驗了一會人生贏家的感覺。上一篇工廠方法模式跟建造者模式還是蠻相似的,有興趣可以翻看,斟酌兩種模式的不同之處,這種方式對學習設計模式幫助巨大。下一篇觀察者模式,敬請關注!
設計模式Java原始碼GitHub下載:https://github.com/jetLee92/DesignPattern
關注我的微信公眾號