又是一個週三,快要下班了,老大突然拉住我,喜滋滋的告訴我:“XX公司很滿意我們做的模型,又簽訂了一個合同,把賓士、寶馬的車輛模型都交給我們公司製作了,不過這次又額外增加了一個需求:汽車的啟動、停止、喇叭聲音、引擎聲音都由客戶自己控制,他想什麼順序就什麼順序, 這個沒問題吧?”
又是一個時間緊,工程量大的專案。首先,我們分析一下需求,賓士、寶馬都是一個產品,它們有共有的屬性,XX公司關心的是單個模型的執行過程:賓士模型A先有引擎聲音,然後再響喇叭;賓士B是先啟動起來,然後再有引擎聲音,這才是XX公司要關心的。那到我們老大這邊呢,就是滿足人家的要求,要什麼順序就立馬能產生什麼順序的模型出來,我就負責老大的要求實現出來,而且還要批量的,也就是說XX公司下單訂購寶馬A車模,我們老大馬上就找我“生產一個這樣的車模, 啟動完畢後,喇叭響一下”,然後我們就準備開始批量生產這些模型。
看起來需求還是比較複雜,我們一個個解決,先從產品類入手。
public abstract class CarModel { private List<String> sequence = new ArrayList<String>(); final public void setSequence( List<String> sequence ) { this.sequence = sequence; } protected abstract void start(); protected abstract void stop(); protected abstract void alarm(); protected abstract void engineBoom(); final public void run() { for ( String actionName : sequence ) { if ( actionName.equalsIgnoreCase( "start" ) ) { this.start(); } else if ( actionName.equalsIgnoreCase( "stop" ) ) { this.stop(); } else if ( actionName.equalsIgnoreCase( "alarm" ) ) { this.alarm(); } else if ( actionName.equalsIgnoreCase( "engine boom" ) ) { this.engineBoom(); } } } }
CarModel的設計原理是這樣的,setSequence方法是允許客戶自己設定一個順序,是要先啟動響一下喇叭再跑起來,還是要先響一下喇叭再啟動。對於一個具體的模型永遠都固定的,但是對於N多個模型就是動態的了。在子類中實現父類的基本方法,run方法讀取sequence, 然後遍歷sequence中的字元呂,哪個字串在先,就先執行哪個方法。
賓士模型程式碼:
public class BenzModel extends CarModel { @Override protected void alarm() { System.out.println( "Benz alarmming" ); } @Override protected void engineBoom() { System.out.println( "Benz startup engine boom" ); } @Override protected void start() { System.out.println( "Benz startting" ); } @Override protected void stop() { System.out.println( "Benz Stopping" ); } }
寶馬模型程式碼:
public class BWMModel extends CarModel { @Override protected void alarm() { System.out.println( "BWM alarmming" ); } @Override protected void engineBoom() { System.out.println( "BWM startup engine boom" ); } @Override protected void start() { System.out.println( "BWM startting" ); } @Override protected void stop() { System.out.println( "BWM Stopping" ); } }
兩個產品類實現都完成,我們來模擬一下XX公司的要求:生產一個賓士模型,要求跑的時候,先發動引擎,然後再掛擋啟動,然後停下來,不需要喇叭。
public class Client { public static void main( String[] args ) { CarModel benz = new BenzModel(); List<String> sequence = new ArrayList<String>(); sequence.add( "engine boom" ); sequence.add( "start" ); sequence.add( "stop" ); benz.setSequence( sequence ); benz.run(); } }
看, 我們組裝了這樣的一輛汽車,滿足了XX公司的需求。但是想想我們的需求, 汽車動作順序是要能夠隨意調整的。所有我們應該為產品模型定義一個建造者,你要啥順序直接告訴建造者,由建造者建造。
這樣才以批量生產某種型別的汽車。
public abstract class CarBuilder { public abstract void setSequence( List<String> sequence); public abstract CarModel getCarModel(); }
public class BenzBuilder extends CarBuilder { private CarModel benz = new BenzModel(); @Override public CarModel getCarModel() { return this.benz; } @Override public void setSequence( List<String> sequence ) { this.benz.setSequence( sequence ); } }
public class BWMBuilder extends CarBuilder { private CarModel bwm = new BWMModel(); @Override public CarModel getCarModel() { return this.bwm; } @Override public void setSequence( List<String> sequence ) { this.bwm.setSequence( sequence ); } }
現在我們生產同一種型別的汽車就容易多了
public class Client { public static void main( String[] args ) { List<String> sequence = new ArrayList<String>(); sequence.add( "engine boom" ); sequence.add( "start" ); sequence.add( "stop" ); BenzBuilder benzBuilder = new BenzBuilder(); benzBuilder.setSequence( sequence ); CarModel benz = benzBuilder.getCarModel(); benz.run(); } }
我們做專案時,經常會有一個共識:需求是無底洞,是無理性的,不可能你告訴它不增加需求就不增加,這4個過程(start,stop,alarm,engineBoom)按照排列組合有很多種,XX公司可以隨意組合,它要什麼順序的車模我就必須生成什麼順序的車輛,客戶就是上帝,所有我們應該找一個導演,指揮各個事件的先後順序,然後為每種順序指定一個程式碼,你說一種我們立刻給你生產處理。