說明:
將某種類產品,生產步驟整理出來。
所有要生產這類產品的 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類別,不用擔心對大杯珍奶、小杯紅茶產生什麼影響,
也不用擔心其他有用到大杯珍奶、小杯紅茶的地方,有沒有什麼其他副作用,修改起來較放心。
所以有句話說,多用組合、少用繼承,因繼承耦合性高,
即使是原開發者,若遇到後續需要更動父類別時,要考量的多了,更動不易了,維護成本就高了。
當然,目前這個例子,用繼承來處理,也沒什麼不妥,
程式不大、之後的更動基本上能估計,那用什麼方式處理,基本上都差不多。