說明:
將某種類產品,生產步驟整理出來。
所有要生產這類產品的 class,均要實現這些標準化步驟。
另外,為避免實際生產時,遺漏某步驟,統一由一個 class,執行一系列的生產步驟。
範例:
製做大杯珍珠奶茶、小杯紅茶。
希望達成如下的效果
static void Main(string[] args) { Director aa = new Director(); Bulider bb = new 大杯珍奶(); aa.setBulider(bb); aa.create(); Console.WriteLine("----------"); bb = new 小杯紅茶(); aa.setBulider(bb); aa.create(); Console.ReadLine(); }執行結果:
拿大杯子
裝珍珠、裝奶茶
拿大蓋子加蓋
拿粗吸管
----------
拿小杯子
裝紅茶
拿小蓋子加蓋
拿細吸管
實現重點在於,大杯珍奶、小杯紅茶物件,都能傳給 Director 操作。
其餘程式碼
//標準化的生產步驟 interface Bulider { void 拿杯子(); void 裝飲料(); void 加蓋子(); void 拿吸管(); } //大杯奶茶生產過程,實作 Bulider 介面 class 大杯珍奶 : Bulider { public void 拿杯子() { Console.WriteLine("拿大杯子"); } public void 裝飲料() { Console.WriteLine("裝珍珠、裝奶茶"); } public void 加蓋子() { Console.WriteLine("拿大蓋子加蓋"); } public void 拿吸管() { Console.WriteLine("拿粗吸管"); } } //小杯紅茶生產過程,實作 Bulider 介面 class 小杯紅茶 : Bulider { public void 拿杯子() { Console.WriteLine("拿小杯子"); } public void 裝飲料() { Console.WriteLine("裝紅茶"); } public void 加蓋子() { Console.WriteLine("拿小蓋子加蓋"); } public void 拿吸管() { Console.WriteLine("拿細吸管"); } } //統一由指揮者 class 執行生產步驟 class Director { private Bulider builder; public void setBulider(Bulider builder) { this.builder = builder; } public void create() { this.builder.拿杯子(); this.builder.裝飲料(); this.builder.加蓋子(); this.builder.拿吸管(); } }
相關連結:設計模式整理列表
作者您好,
回覆刪除寫的相當清楚,淺顯易懂,但有個疑問想請教,
請問
Director aa = new Director();
Bulider bb = new 大杯珍奶();
aa.setBulider(bb);
aa.create();
Console.WriteLine("----------");
bb = new 小杯紅茶();
aa.setBulider(bb);
aa.create();
與
Drink a = new 大杯珍奶();
Drink b = new 小杯紅茶();
// 其中大杯珍奶與小杯紅茶都是繼承Drink類別
兩種寫法皆是把複雜的創建過程隱藏,那差別在哪裡呢
差在耦合性。
刪除猜測您繼承的Drink父類別,應該包含了建造者模式中Director中的行為(例如create)。
若之後需要動到Drink父類別時,
繼承的寫法,須謹慎考量對底下子類別(大杯珍奶、小杯紅茶)會發生什麼影響,
其他有用到子類別(大杯珍奶、小杯紅茶)的地方,可能都要審視一遍,否則系統可能就爆了。
若用Director的方式處理,比較像將獨立的物件組合起來一樣,
更動Director類別,不用擔心對大杯珍奶、小杯紅茶產生什麼影響,
也不用擔心其他有用到大杯珍奶、小杯紅茶的地方,有沒有什麼其他副作用,修改起來較放心。
所以有句話說,多用組合、少用繼承,因繼承耦合性高,
即使是原開發者,若遇到後續需要更動父類別時,要考量的多了,更動不易了,維護成本就高了。
當然,目前這個例子,用繼承來處理,也沒什麼不妥,
程式不大、之後的更動基本上能估計,那用什麼方式處理,基本上都差不多。