今天有位朋友問我一個有趣的問題:如何實現 OrWhere 的功能?我推測他想要達成的效果如下:
static IEnumerable<int> MorePredicate(IEnumerable<int> source)
{
return source.OrWhere(i => i > 0); // 或所有的正數
}
static void Main(string[] args)
{
var array = Enumerable.Range(-5, 10).ToArray();
var odd = array.Where(i => i % 2 != 0); // 排除所有偶數
var oddOrPositive = MorePredicate(odd);
foreach (var i in oddOrPositive)
{
Console.WriteLine(i);
}
}
上述程式碼預期應輸出 -5、-3、-1、1、2、3、4。但顯然這段程式碼無法編譯通過,也無法透過擴充類庫來實現。因為在 Main 方法中 Where 過濾後,已經排除了所有偶數,後續程式碼無法從新序列中恢復已被移除的元素。
不過這個需求讓我想起了 Specification 模式。Specification 模式的核心在於構建可自由組裝的業務邏輯元素。Specification 類別擁有一個 IsSatisfiedBy 方法,用於驗證某個物件是否符合該 Specification 所代表的條件。多個 Specification 物件可以組合生成新的 Specification 物件,從而形成高度可客製化的業務邏輯。例如,我們可以透過依賴注入(控制反轉)的方式配置業務邏輯,確保系統的靈活性。
如果您點開維基百科的連結,會發現相關描述大約是一個英翻中的練習。抄完「定義」後,再來看看同樣引自維基百科的 UML 圖:
一般來說,Specification 模式意味著實現如下介面:
public interface ISpecification<T>
{
bool IsSatisfiedBy(T candidate);
ISpecification<T> And(ISpecification<T> other);
ISpecification<T> Or(ISpecification<T> other);
ISpecification<T> Not();
}