建造者模式简介
建造者模式聽起來有點高大上, 也是程序猿之間常常提起的模式之一.
其實它有1個前提跟模板方法模式(Template Method)有點類似, 就是建造這個過程可以分拆成若干個部分(步驟).
我們先看定義.
一, 建造者模式的定義
建造者模式(Builder),? 將1個復雜對象的構建與它的表示分離.? 使得同樣的構建過程可以創建不同的表示.
定義很簡練啊.
關鍵詞如下:
什么是 構建?
什么是 表示?
什么是 分離?
這里先簡單解釋一下:
構建:
??????? 就是完成1件由若干步驟組成的過程.
表示:
?????? 就是將對象表達出來(文字表達, 圖形表達..等)
分離:
?????? 就是代碼寫在不同的類中.
下面舉幾個例子詳解.
二, 使用模板方法模式 實現 汽車制造的1個簡單例子.
我們假設, suppose, 1輛汽車的制造過程只有3步:
1. 制造引擎.
2. 制造車身.
3. 制造論壇
現在要求做1個可以實現 制造Fort汽車 和 Benz汽車 的類設計.
我們以前講過, 模板方法可以實現步驟分離.
那么先試著使用模板方法實現:
2.1 抽象類MakeCar
public abstract class MakeCar {private ArrayList<String> partList = new ArrayList<String>();ArrayList<String> getPartList(){return this.partList;}abstract void buildEngine();abstract void buildBody();abstract void buildwheels();public void build(){this.buildEngine();this.buildBody();this.buildwheels();}public void show(){System.out.println(this.getClass().getSimpleName() + ": " + this.getPartList());}
}
注意,
里面的 build() 相當于構建(由若干步驟組成)
里面的 show() 就相當于表示了.
2.2 類MakeFortCar
public class MakeFortCar extends MakeCar{@Overridevoid buildEngine() {// TODO Auto-generated method stubthis.getPartList().add("Fort-Engine");}@Overridevoid buildBody() {// TODO Auto-generated method stubthis.getPartList().add("Fort-Body");}@Overridevoid buildwheels() {// TODO Auto-generated method stubthis.getPartList().add("Fort-wheels");}}
2.3 類MakeFortCar
public class MakeBenzCar extends MakeCar{@Overridevoid buildEngine() {// TODO Auto-generated method stubthis.getPartList().add("Benz-Engine");}@Overridevoid buildBody() {// TODO Auto-generated method stubthis.getPartList().add("Benz-Body");}@Overridevoid buildwheels() {// TODO Auto-generated method stubthis.getPartList().add("Benz-wheels");}}2.4 客戶端代碼:
MakeCar mFort = new MakeFortCar();mFort.build();mFort.show();MakeCar mBenz = new MakeBenzCar();mBenz.build();mBenz.show();
這種寫法的優點:
1.在客戶端隱藏了構造過程的細節, 這個也是模板方法模式的優點.
2. 可以有多個子類繼承同1個模板, 也就是同樣可以實現一樣可以實現 1個構建過程可以創建不同的表示.
然后看看這樣的寫法有什么缺點:
1. 看起來是汽車自己制造了自己, 沒有1個建設者的角色存在. 無角色區別.
2. 構建方法build() 跟表示方法 show()寫在同1個類. 沒有分離
3. 若現實中構建方法build() , 也就是建造順序一但修改, 若遵循封閉-開放 原則,則整套代碼不適用了.?
??? 因為模板方法之所以叫做模板方法, 是因為模板本身是不改的, 一套類對應1個模板.
??? 而, 汽車生產中, 建造順序往往會有變化, 甚至有額外的工序. 例如貨車需要1個集裝箱等.
三, 使用建造者模式實現上面的例子.
建設者模式的角色有3個.
1. 產品(product)?????? 就是指建造的產品, 這個例子指的就是汽車. 它有方法可以表示自己.
2. 建設者(Builder)?? 整個模式的核心, 它負責怎樣去實現產品中每個部分(零件)的制造.
3. 指揮者(Director)? 相當于1個項目經理模式, 它指揮產品中每個部分的完成順序.
從解釋中大概已經估算出, 構建方法在指揮者里,? 表示方法在產品里.
具體代碼如下:
3.1 產品類CarProduct:
import java.util.ArrayList; public class CarProduct {private ArrayList<String> partList = new ArrayList<String>();private String brandName;void addPart(String part){this.partList.add(part);}void setbrand(String name){this.brandName = name;}public void show(){System.out.println(this.brandName + ":" + partList);} }注意這里數組添加的部分是String格式, 實際項目中很可能是1個對象(零件類對象)
3.2 抽象建設者類CarBuilder
public abstract class CarBuilder {private CarProduct prod = new CarProduct();CarProduct getProd() {return prod;}void setProd(CarProduct prod) {this.prod = prod;}abstract void setBrand();abstract void buildEngine();abstract void buildBody();abstract void buildWheels(); }3.3 FortCarBuilder
public class FortCarBuilder extends CarBuilder {@Overridevoid setBrand() {// TODO Auto-generated method stubthis.getProd().setbrand("Fort");}@Overridevoid buildEngine() {// TODO Auto-generated method stubthis.getProd().addPart("Fort-Engine");}@Overridevoid buildBody() {// TODO Auto-generated method stubthis.getProd().addPart("Fort-Body");}@Overridevoid buildWheels() {// TODO Auto-generated method stubthis.getProd().addPart("Fort-Wheels");}}3.4 BenzCarBuilder
public class BenzCarBuilder extends CarBuilder {@Overridevoid setBrand() {// TODO Auto-generated method stubthis.getProd().setbrand("Benz");}@Overridevoid buildEngine() {// TODO Auto-generated method stubthis.getProd().addPart("Benz-Engine");}@Overridevoid buildBody() {// TODO Auto-generated method stubthis.getProd().addPart("Benz-Body");}@Overridevoid buildWheels() {// TODO Auto-generated method stubthis.getProd().addPart("Benz-Wheels");}}3.5 指揮者CarDirector()
public class CarDirector {public void construct(CarBuilder cb){cb.setBrand();cb.buildEngine();cb.buildBody();cb.buildWheels();} }3.6 客戶端代碼:
CarProduct prod;CarDirector cd = new CarDirector();CarBuilder cb = new FortCarBuilder();cd.construct(cb);prod = cb.getProd();prod.show();cb = new BenzCarBuilder();cd.construct(cb);prod = cb.getProd();prod.show();3. 7 UML
3. 8 這樣用建造者模式實現的好處
1. 從客戶端代碼, 出現了指揮者, 建造者, 產品3種角色, 就如指揮者指揮建造者建造了產品一樣.?? 跟業務邏輯結合得好
??? 當然, 這個例子1個建造者(builder)只生產1個產品.
2. 構建過程卸載指揮者類里,? 表示方法寫在產品類里,? 也就是構建過程與表示分離.
3. 同1個指揮者實現了兩種產品(Fort Benz)的生產和表示, 也就是定義中的1個構建過程可以實現不同的表示.
4. 當某個產品的制造順序改變是, 只需要新增1個指揮者子類,? 讓新的指揮者去指揮建設者生產就可以了. 其他類不受影響.
???? 也就是說這種改動符合封閉 - 開放原則.
總結
- 上一篇: 外观模式(Facade) - 为系统分层
- 下一篇: 观察者模式(Observer) 简介