<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

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

      2009-09-28 10:34  Jeffrey Zhao  閱讀(13670)  評論(12)    收藏  舉報

      Specification模式的作用是構(gòu)建可以自由組裝的業(yè)務(wù)邏輯元素。不過就上篇文章的示例來看,“標準”的Specification模式的實現(xiàn)還是比較麻煩的,簡單的功能也需要較復雜的代碼。不過,既然說是“標準”的方式,自然就是指可以在任意面向?qū)ο笳Z言中使用的實現(xiàn)方式,不過我們使用的是C#,在實際開發(fā)過程中,我們可以利用C#如今的強大特性來實現(xiàn)出更容易使用,更輕量級的Specification模式。

      當然,有利也有弊,在使用“標準”還是“輕量級”的問題上,還要根據(jù)你的需求來進行選擇。

      Specification模式的關(guān)鍵在于,Specification類有一個IsSatisifiedBy函數(shù),用于校驗?zāi)硞€對象是否滿足該Specification所表示的條件。多個Specification對象可以組裝起來,并生成新Specification對象,這便可以形成高度可定制的業(yè)務(wù)邏輯。從中可以看出,一個Specification對象的關(guān)鍵,其實就是一個IsSatisifiedBy方法的邏輯。每種對象,一段邏輯。每個對象的唯一關(guān)鍵,也就是這么一段邏輯。因此,我們完全可以構(gòu)造這么一個“通用”的類型,允許外界將這段邏輯通過構(gòu)造函數(shù)“注入”到Specification對象中:

      public class Specification<T> : ISpecification<T>
      {
          private Func<T, bool> m_isSatisfiedBy;
      
          public Specification(Func<T, bool> isSatisfiedBy)
          {
              this.m_isSatisfiedBy = isSatisfiedBy;
          }
      
          public bool IsSatisfiedBy(T candidate)
          {
              return this.m_isSatisfiedBy(candidate);
          }
      }

      嗯嗯,這也是一種依賴注入。在普通的面向?qū)ο笳Z言中,承載一段邏輯的最小單元只能是“類”,只是我們說,某某類中的某某方法就是我們需要的邏輯。而在C#中,從最早開始就有“委托”這個東西可用來承載一段邏輯。與其為每種情況定義一個特定的Specification類,讓那個Spcification類去訪問外部資源(即建立依賴),不如我們將這個類中唯一需要的邏輯給準備好,各種依賴直接通過委托由編譯器自動保留,然后直接注入到一個“通用”的類中。很關(guān)鍵的是,這樣在編程方面也非常容易。

      至于原本ISpecification<T>中的And,Or,Not方法,我們可以將它們提取成擴展方法。有朋友說,既然有了擴展方法,那么對于一些不需要訪問私有成員/狀態(tài)的方法,都應(yīng)該提取到實體的外部,避免“污染”實體。不過我不同意,在我看來,到底是用實例方法還是擴展方法,還是個根據(jù)職責和概念而一定的。我在這里打算使用擴展的目的,是因為And,Or,Not并非是一個Specification對象的邏輯,并不是一個Specification對象說,“我要去And另一個”,“我要去Or另一個”,或者“我要造……取反”。就好比二元運算符&&、||、或者+、-,左右兩邊的運算數(shù)字有主次之分嗎?沒有,它們是并列的。因此,我選擇使用額外的擴展方法,而不是將這些職責交給某個Specification對象:

      public static class SpecificationExtensions
      {
          public static ISpecification<T> And<T>(
              this ISpecification<T> one, ISpecification<T> other)
          {
              return new Specification<T>(candidate =>
                  one.IsSatisfiedBy(candidate) && other.IsSatisfiedBy(candidate));
          }
      
          public static ISpecification<T> Or<T>(
              this ISpecification<T> one, ISpecification<T> other)
          {
              return new Specification<T>(candidate =>
                  one.IsSatisfiedBy(candidate) || other.IsSatisfiedBy(candidate));
          }
      
          public static ISpecification<T> Not<T>(this ISpecification<T> one)
          {
              return new Specification<T>(candidate => !one.IsSatisfiedBy(candidate));
          }
      }
      

      此外,使用擴展方法的好處在于,如果我們想要加一個邏輯運算(如“異或”),那么是不需要修改接口的。修改接口是一件勞民傷財?shù)氖虑?/a>。

      至此,我們使用Specification對象就容易多了,因為不需要為每段邏輯創(chuàng)建一個獨立的ISpecification<T>類型。但是,其實還有更簡單的:直接使用委托。既然整個Specificaiton對象的邏輯可以使用一個委托直接表示,那為什么我們還需要一個“外殼”呢?不如直接使用這樣的委托類型:

      public delegate bool Spec<T>(T candicate);

      當然,您也可以直接使用Func<T, bool>。我在這里創(chuàng)建Spec的目的,是因為我想“明確”這里其實是一個Specification,而不是一個普通的“接受T作為參數(shù),返回bool的方法”。于是現(xiàn)在,我們便可以用這樣的擴展方法來編寫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模式比之前要容易許多。不過,在某些時候,我們可能還是需要老老實實按照標準來做。創(chuàng)建獨立的Specification對象的好處是在一個單獨的地方內(nèi)聚地封裝了一段邏輯,因此適合較集中,較“重”的邏輯,而“委托”則適合輕便的實現(xiàn)。委托的另一個優(yōu)勢是使用方便,但它的缺點便是難以“靜態(tài)表示”。如果您在使用Specification模式時,需要根據(jù)外部配置來決定進行何種組裝,那么可能只有為每種邏輯創(chuàng)建獨立的Specification對象了。此外,使用委托還有一個“小缺點”,即它可能會“不自覺”地提升對象的生命周期,可能會形成一些延遲方面的陷阱

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

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

      主站蜘蛛池模板: 国产做a爱片久久毛片a片| 阿克苏市| 18禁免费无码无遮挡网站| 91密桃精品国产91久久| 99久久精品国产一区二区暴力| 国产午夜A理论毛片| 国产精品成人网址在线观看| 亚洲AV天天做在线观看| 免费午夜无码片在线观看影院| 在线观看中文字幕国产码| 日本一区二区三区免费播放视频站| 亚洲中文字幕av无码区| 国内揄拍国内精品对久久| 久久婷婷五月综合97色直播| 免费三级网站| 噜噜综合亚洲av中文无码| 在线国产精品中文字幕| 无码av中文一区二区三区桃花岛| 日日麻批免费40分钟无码| 久久毛片少妇高潮| 亚洲欧洲美洲在线观看| 亚洲一区二区色情苍井空| 国产精品国三级国产专区| 尹人香蕉久久99天天拍| 国产a在视频线精品视频下载 | 日本国产精品第一页久久| ww污污污网站在线看com| 日韩精品一区二区亚洲av| 最近中文国语字幕在线播放| 人妻在线无码一区二区三区| 国产精品一区 在线播放| 少妇粉嫩小泬喷水视频www| 午夜精品一区二区三区成人| 国产另类ts人妖一区二区| 全国最大成人网| 亚洲国产日韩欧美一区二区三区| 国产农村妇女高潮大叫| 国内精品久久人妻无码不卡| 午夜免费啪视频| 少妇极品熟妇人妻| 在线日韩日本国产亚洲|