一、概述 建造者模式很容易讓人想到建房子,不管建剛需房、改善房還是別墅,它們都離不開地基、柱子、層面和牆體這些組成部分,建築工人就是把這些組成部分一個個建起來,最後連成一體建出一棟棟樓房。 來看看建造者模式的定義,將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建房子的過程 ...
一、概述
建造者模式很容易讓人想到建房子,不管建剛需房、改善房還是別墅,它們都離不開地基、柱子、層面和牆體這些組成部分,建築工人就是把這些組成部分一個個建起來,最後連成一體建出一棟棟樓房。
來看看建造者模式的定義,將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建房子的過程都是相似的,但可以建出形形色色的房子。
二、結構類圖
三、應用實例
我們用製造自行車為例子講解建造者模式,自行車由車架、輪胎、腳踏等部件組成,如下圖所示。自行車製造公司就是把這些零部件組裝起來。
自行車製造公司的工程部門相當於指揮者,生產部門相當於建造者,當今共用單車做的比較大的摩拜和ofo相當於客戶,單車就是產品了。結構圖如下所示:
一起來看看如何用代碼來實現
1、定義創建者介面,也就是生產線介面
package com.jet.pattern.builder; import com.jet.pattern.builder.impl.Bike; /** * description: * 自行車生產線介面 * Created by chenzanjin on 2017/2/22. */ public interface BikeBuilder { // 組裝輪胎 public void buildTyres(); // 組裝車架 public void buildFrame(); // 組裝GPS定位裝置 public void buildGPS(); // 獲取自行車 public Bike getBike(); }
2、定義摩拜單車生產線
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 摩拜單車生產線 * Created by chenzanjin on 2017/2/22. */ public class MoBikeBuilder implements BikeBuilder { // 擁有單車對象 Bike bike = new Bike(); @Override public void buildTyres() { bike.setTyre("橙色輪胎"); } @Override public void buildFrame() { bike.setFrame("橙色車架"); } @Override public void buildGPS() { bike.setGps("mobike定製版GPS定位裝置"); } @Override public Bike getBike() { return bike; } }
3、定義ofo單車生產線
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * ofo單車生產線 * Created by chenzanjin on 2017/2/22. */ public class OfoBikeBuilder implements BikeBuilder { // 擁有單車對象 Bike bike = new Bike(); @Override public void buildTyres() { bike.setTyre("黑色輪胎"); } @Override public void buildFrame() { bike.setFrame("黃色車架"); } @Override public void buildGPS() { bike.setGps("ofo定製版GPS定位裝置"); } @Override public Bike getBike() { return bike; } }
4、定義單車對象
package com.jet.pattern.builder.impl; /** * description: * 自行車對象 * Created by chenzanjin on 2017/2/22. */ public class Bike { // 輪胎 private String tyre; // 車架 private String frame; // GPS定位裝置 private String gps; public String getTyre() { return tyre; } public void setTyre(String tyre) { this.tyre = tyre; } public String getFrame() { return frame; } public void setFrame(String frame) { this.frame = frame; } public String getGps() { return gps; } public void setGps(String gps) { this.gps = gps; } }
5、定義工程部
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 工程部門作為指揮者,可以指導生產部門作業 * Created by Administrator on 2017/2/22. */ public class EngineeringDepartment { // 用戶告知指揮者想要什麼樣的單車 BikeBuilder bikeBuilder; public EngineeringDepartment(BikeBuilder bikeBuilder){ this.bikeBuilder = bikeBuilder; } // 指導組裝單車 public void Construct(){ bikeBuilder.buildTyres(); bikeBuilder.buildFrame(); bikeBuilder.buildGPS(); } }
6、測試類
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 建造者測試類 * Created by Administrator on 2017/2/22. */ public class Test { public static void main(String[] args) { // 建造摩拜單車 BikeBuilder moBikeBuilder = new MoBikeBuilder(); EngineeringDepartment ed1 = new EngineeringDepartment(moBikeBuilder); ed1.Construct();// 指導組裝 // 產出單車,體現建造和顯示分離 Bike moBike = moBikeBuilder.getBike(); // 建造ofo單車 BikeBuilder ofoBikeBuilder = new MoBikeBuilder(); EngineeringDepartment ed2 = new EngineeringDepartment(ofoBikeBuilder); ed2.Construct();// 指導組裝 Bike ofoBike = ofoBikeBuilder.getBike(); } }
四、優缺點
1、優點
(1)、產品的建造和表示分離,實現瞭解耦。
(2)、隱藏了產品的建造細節,用戶只需關心產品的表示,而不需要瞭解是如何創建產品的。
(3)、體現了開閉原則,如上代碼所示,如果需要再生產其他共用單車,只需要再開一條生產線即可,不影響其他生產線的作業。
2、缺點
(1)、當建造者過多時,會產生很多類,難以維護。
五、總結
建造者模式的使用場合是當創建複雜對象時,把創建對象成員和裝配方法分離出來,放在建造者類中去實現,用戶使用該複雜對象時,不用理會它的創建和裝配過程,只關心它的表示形式。其實完全理解這個模式還是要一番思考的,難以搞懂的是指揮者似乎沒什麼存在的必要,在代碼里也沒體現它的作用,我們也可以把指揮者的方法放在建造者裡面,但為什麼沒有這樣做呢?我想這可能是考慮到單一責任原則,建造者只負責創建對象的各個部分,至於各個部分創建的順序、裝配方法它就不管了。還有就是當順序要改變時,建造者可以不用改動,改動指揮者就好了,指揮者只有一個,建造者有很多,要改建造者就麻煩了。