有用過 jQuery 的人應該會對它的方法鏈 (method chain) 印象深刻吧,一條龍的方法呼叫可以簡化很多程式碼量,雖然看起來有點不容易維護,但就不需要特別設定的程式撰寫上,它還是一個很方便的 pattern。
有用過 jQuery 的人應該會對它的方法鏈 (method chain) 印象深刻吧,一條龍的方法呼叫可以簡化很多程式碼量,雖然看起來有點不容易維護,但就不需要特別設定的程式撰寫上,它還是一個很方便的 pattern,它在 .NET 上也可以實作的出來,只是有個問題,在 JavaScript 上是弱型別 (weak type) 環境,但 .NET 是強型別 (strong type) 的環境,如果用 object 來實作,反而會有很多問題,像是這樣:
{
// object's MathExpression
public class MathExpression
{
private int _value;
public MathExpression(int InitialValue)
{
this._value = InitialValue;
}
public object Add(int Value)
{
this._value += Value;
return this;
}
public object Subtract(int Value)
{
this._value -= Value;
return this;
}
public object Multiply(int Value)
{
this._value *= Value;
return this;
}
public object Divide(int Value)
{
this._value /= Value;
return this;
}
public int GetValue()
{
return this._value;
}
}
}
光是呼叫上的撰寫就會累死人;
((((op.Add(100) as MathExpression)
.Add(100) as MathExpression)
.Divide(50) as MathExpression)
.Subtract(100) as MathExpression)
.Multiply(5);
當然,也可以直接回傳 MathExpression,但是這樣就會有高耦合性的問題,例如我今天如果要換成 double 型別,float 型別,long 型別或 decimal 型別時,是否就要整個重寫?這時候就有個好方法,就是使用介面來做,這樣的介面設計稱為 Fluent Interface (流利介面),由 Eric Evans 和 Martin Fowler 提出,它有三個特性:
1. 透過呼叫方法來定義物件內容。
2. 物件會自我參考 (self-referential),且新的物件內容會和最後一個物件內容等價。
3. 透過回傳一個 void 內容 (簡單的說就是 null 或不回傳最後的物件內容) 結束。
它的實作也很簡單,以上面 MathExpression 為例,我們宣告了一個 IMathExpression 介面:
{
IMathExpression Add(int Value); // +
IMathExpression Subtract(int Value); // -
IMathExpression Multiply(int Value); // *
IMathExpression Divide(int Value); // /
int GetValue();
}
然後使用 MathExpressionImpl 來實作它:
{
private int _value;
public MathExpressionImpl(int InitialValue)
{
this._value = InitialValue;
}
public IMathExpression Add(int Value)
{
this._value += Value;
return this;
}
public IMathExpression Subtract(int Value)
{
this._value -= Value;
return this;
}
public IMathExpression Multiply(int Value)
{
this._value *= Value;
return this;
}
public IMathExpression Divide(int Value)
{
this._value /= Value;
return this;
}
public int GetValue()
{
return this._value;
}
}
整個 Fluent Interface 的重點是,介面的成員都會回傳自己,但對物件的控制都由介面成員來做,這樣也可以保有封裝的優點,而回傳介面的方式可確保在執行完方法後取得的一定是最新的物件,而且和一開始就建置的物件是相同的。
用戶端程式寫起來就很輕鬆:
op2.Add(100).Add(100).Divide(50).Subtract(100).Multiply(5);
Fluent Interface 適合用在需要對一個相同物件進行大量設定或方法呼叫的場合,它可以簡化不少的程式碼撰寫量,不過若沒有這樣的需求,那麼也許就不太適用。
Reference: