一開始在做開發的時候,可能會因為專案小,
或是時間上的因素使用工廠模式(或是不使用任何的設計模式)來撰寫程式。
但常常會發現經過開發週期不斷的迭代(或是用戶需求的改變),
創建的模式變的不再那麼的單純,
導致原先設計的創見模型變得不再那麼的好使。
這時可能會考慮另一種模式來幫我們解決問題-生成器模式。
將實例化的過程抽象化,再透過不同實作方式來完成不同屬性的物件(Object)
在決定是否使用生成器模式之前,可以用兩個原則來思考:
在開發上若同時遇到這兩個問題的時候,就可以考慮使用這種設計模式。
像是建立遊戲角色的時候,同時就要考慮創建甚麼角色(可能是不同職位、種族之類的問題),
也要考慮怎麼創建這隻角色(能力值、外觀...等對角色的影響)。
或是...
公司的表單簽核系統要考慮創建甚麼畫面(可能是職位或權限對一些欄位的影響),
也要考慮要有哪些欄位(可能是採購的產品、價位...等)
假設我們需要做一個採購單畫面,畫面上有採購項目、商品價格、是否同意採購 3個欄位:
這時候我們要怎麼設計呢?
//建立一個生成器的抽象類別
abstract class AbstractViewBuilder{
private Component name;
private Component price;
private Component isPassed;
public AbstractViewBuilder setItemName(string name);
public AbstractViewBuilder setItemPrice(int price);
public AbstractViewBuilder setIsPassed(bool isPassed);
//TODO: 將上面這些元件組成一個畫面
public Page build{...}
}
//建立實作AbstractViewBuilder 的類別 ApplicantViewBuilder 、ProcurementStaffViewBuilder
class ApplicantViewBuilder : AbstractViewBuilder{
//回傳一個TextBox:Component 讓使用者可以填寫
public AbstractViewBuilder setItemName(string name){
TextBox com = new TextBox();
//TODO:做一些處理
this.name = com;
return this;
}
//回傳一個Lable:Component 不讓使用者填寫
public AbstractViewBuilder setItemPrice(int Price){
Lable com = new Lable();
//TODO:做一些處理
this.price = com;
return this;
}
//回傳一個Lable:Component 不讓使用者填寫
public AbstractViewBuilder setIsPassed(){
Lable com = new Lable();
//TODO:做一些處理
this.isPassed = com;
return this;
}
}
class ProcurementStaffViewBuilder : AbstractViewBuilder{
//回傳一個Lable:Component 讓使用者可以填寫
public AbstractViewBuilder setItemName(string name){
Lable com = new Lable();
//TODO:做一些處理
this.name = com;
return this;
}
//回傳一個TextBox:Component 不讓使用者填寫
public AbstractViewBuilder setItemPrice(int Price){
TextBox com = new TextBox();
//TODO:做一些處理
this.price = com;
return this;
}
//回傳一個Lable:Component 不讓使用者填寫
public AbstractViewBuilder setIsPassed(){
Lable com = new Lable();
//TODO:做一些處理
this.isPassed = com;
return this;
}
}
//建立Diractor類別
class Diractor{
public Page createView(AbstractViewBuilder builder){
//建立頁面
builder.setItemName("")
.setItemPrice(0)
.setIsPassed(false);
return builder.build();
}
}
static void main(){
bool isApplicant = true;
bool isProcurementStaff = false;
var diractor = new Diractor();
//判斷是哪一個職員進入畫面
AbstractViewBuilder builder = null;
if(isApplicant){
builder = new ApplicantViewBuilder();
}
else if (isProcurementStaff){
builder = new ProcurementStaffViewBuilder();
}
//這樣就建立完成一個頁面了
diractor.createView(build);
}
這樣的撰寫方式,在未來有個新的頁面需求,我們可以很簡單新增一個類別就能完成。
最後這邊可以思考看看兩個問題: