程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 趣味編程:C#中Specification模式的實現(參考答案 - 上)(2)

趣味編程:C#中Specification模式的實現(參考答案 - 上)(2)

編輯:關於C語言

當然,您也可以直接使用Func<T, bool>。我在這裡創建Spec的目的,是因為我想“明確”這裡其實是一個Specification,而不是一個普通的“接受T作為參數,返回 bool的方法”。於是現在,我們便可以用這樣的擴展方法來編寫And,Or和Not:

public static class SpecExtensions 
{
  public static Spec<T> And<T>(this Spec<T> one, Spec<T> other)
  {
    return candidate => one(candidate) && other(candidate);
  }

  public static Spec<T> Or<T>(this Spec<T> one, Spec<T> other)
  {
    return candidate => one(candidate) || other(candidate);
  }

  public static Spec<T> Not<T>(this Spec<T> one)
  {
    return candidate => !one(candidate);
  }
}

用它來編寫上次的示例便容易多了:

static Spec<int> MorePredicate(Spec<int> original)
{
  return original.Or(i => i > 0);
}

static void Main(string[] args)
{
  var array = Enumerable.Range(-5, 10).ToArray();
  var oddSpec = new Spec<int>(i => i % 2 == 1);
  var oddAndPositiveSpec = MorePredicate(oddSpec);

  foreach (var item in array.Where(i => oddAndPositiveSpec(i)))
  {
    Console.WriteLine(item);
  }
}

由於有C#的擴展方法和委托,在C#中使用Specification模式比之前要容易許多。不過,在某些時候,我們可能還是需要老老實實按照標准來做。創建獨立的Specification對象的好處是在一個單獨的地方內聚地封裝了一段邏輯,因此適合較集中,較“重”的邏輯,而“委托”則適合輕便的實現。委托的另一個優勢是使用方便,但它的缺點便是難以“靜態表示”。如果您在使用Specification模式時,需要根據外部配置來決定進行何種組裝,那麼可能只有為每種邏輯創建獨立的Specification對象了。此外,使用委托還有一個“小缺點”,即它可能會“不自覺”地提升對象的生命周期,可能會形成一些延遲方面的陷阱。

當然,我並不是說獨立Specification對象就不會造成生命周期延長——只要功能實現一樣,各方面也應該是相同的。只不過獨立的Specificaiton對象給人一種“正式”而“隆重”的感覺,容易讓人警覺,因而緩解了這方面問題。

不過還有一個問題我們還沒有解決——我們現在組裝的是委托或Specification對象,但如果我們需要組裝一個表達式樹,組裝完畢後交給如LINQ to SQL使用,又該怎麼做呢?我們的“下”便會設法解決這個問題。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved