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

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

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

      青梅煮酒論C#:Specification pattern

      2011-01-16 13:56  空逸云  閱讀(3316)  評論(17)    收藏  舉報

      Specification模式早在3個多月前,閱讀一個開源博客的時候便接觸到了.但并沒多少深入.最近,抽空將其好好研究了一番,果然,其魅力的確能讓你回味無窮,那現在,就讓我們零距離接觸Specification模式吧!

      何為Specification?

      Specification,中文有翻譯規格,雖然有很多爭論,但目前叫得最多的,還是規格模式,既然說到了規格,那其作用估計就能不言而喻了.

      Specification模式的作用是構建可以自由組裝的業務邏輯元素.

      上面這句話可以完整的概括Specification的作用,但第一次理解或許會有些許困難,沒關系,可以這么理解,Specification模式起作用的,是每個Specification類,每一個Specification類,可以看成一張"規格書",或者說是某種"規格約束",而通過這張"規格書"或者"規格約束",我們能得到我們所想要的這種"規格"的對象,并且,不同的規格是可以組合起來,形成新的規格.如果還不明白.好吧,您知道樂高積木吧?我們形象的把每個規格想象成一個不同的樂高模型,而不同的樂高模型組合在一起了,就形成了新的模型,以達到我們所需的結果.

      specification-pattern-uml

      如何實現Specification

      了解了什么是Specification,那接下去,您肯定會問,該怎么實現?其實很簡單,Specification模式里面只有一個方法,我們有了"規格書",下一步,當然就是從不同的對象中得到符合"規格書"的對象,那這個匹配的過程就形成了一個動作抽象.IsSatisfiedBy就是幫助你從"對象堆"中找到你所需"規格"的動作.如此.我們可以實現的Specification接口如下

          public interface ISpecification<T>
          {
      
              bool IsSatisfiedBy(T candidate);
      
          }

      但是,一般的Specification都提供了幾個基本的組合操作,例如Add,Or,Not,可以利用它們分別組合成一個新的Specification.經過初步改動,最后ISpecification如下

          public interface ISpecification<T>
          {
      
              bool IsSatisfiedBy(T candidate);
      
              ISpecification<T> Add(ISpecification<T> other);
      
              ISpecification<T> Or(ISpecification<T> other);
      
              ISpecification<T> Not();
      
          }

      為了重用可復用邏輯,我們定義了一個抽象類CompositeSpecification

          public abstract class CompositeSpecification<T> : ISpecification<T>
          {
      
              public abstract bool IsSatisfiedBy(T candidate);
      
              public ISpecification<T> Add(ISpecification<T> other)
              {
      
                  return new AddSpecification<T>(this, other);
      
              }
      
              public ISpecification<T> Or(ISpecification<T> other)
              {
      
                  return new OrSpecification<T>(this, other);
      
              }
      
              public ISpecification<T> Not()
              {
      
                  return new NotSpecification<T>(this);
      
              }
      
          }

      并定義了基本的幾個"組合"類

          public class AddSpecification<T> : CompositeSpecification<T>
          {
      
              private ISpecification<T> one;
      
              private ISpecification<T> other;
      
              public AddSpecification(ISpecification<T> one, ISpecification<T> other)
              {
      
                  this.one = one;
      
                  this.other = other;
      
              }
      
              public override bool IsSatisfiedBy(T candidate)
              {
      
                  return one.IsSatisfiedBy(candidate) && other.IsSatisfiedBy(candidate);
      
              }
      
          }
      
          public class OrSpecification<T> : CompositeSpecification<T>
          {
      
              private ISpecification<T> one;
      
              private ISpecification<T> other;
      
              public OrSpecification(ISpecification<T> one, ISpecification<T> other)
              {
      
                  this.one = one;
      
                  this.other = other;
      
              }
      
              public override bool IsSatisfiedBy(T candidate)
              {
      
                  return one.IsSatisfiedBy(candidate) || other.IsSatisfiedBy(candidate);
      
              }
      
          }
      
          public class NotSpecification<T> : CompositeSpecification<T>
          {
      
              private ISpecification<T> one;
      
              public NotSpecification(ISpecification<T> one)
              {
      
                  this.one = one;
      
              }
      
              public override bool IsSatisfiedBy(T candidate)
              {
      
                  return !one.IsSatisfiedBy(candidate);
      
              }
      
          }

      最后,我們定義我們所需要的規格,在這里,我們定義一個基數規格與正數規格

          public class OddSpecification : ComsptionSpecification<int>
          {
      
              public override bool IsSatisfiedBy(int candidate)
              {
      
                  return candidate % 2 != 0;
      
              }
      
          }
      
          public class PlusSpecification : ComsptionSpecification<int>
          {
      
              public override bool IsSatisfiedBy(int candidate)
              {
      
                  return candidate > 0;
      
              }
      
          }
      

      現在,萬事俱備,只欠東風.就差你來調用了.

              static void Main(string[] args)
              {
      
                  var items = Enumerable.Range(-5, 10);
      
                  ISpecification<int> oddSpec = new OddSpecification();
      
                  var spec = MoreCandidate(oddSpec);
      
                  foreach (var i in items.Where(it => spec.IsSatisfiedBy(it)))
                  {
      
                      Console.WriteLine(i);
      
                  }
      
              }
      
              static ISpecification<int> MoreCandidate(ISpecification<int> spec)
              {
      
                  ISpecification<int> plusSpec = new PlusSpecification();
      
                  return spec.Or(plusSpec);
      
              }

      這個邏輯還是十分簡單的.我們先定義了一個基數規格,后面我們發現這個規格不足以得到我們所需要的,我們想OrWhere它是正數.于是,我們"組合"成了一個新的規格.結果

      clip_image002

      這里應該注意的是.在這里我們提供了一種OrWhere功能,這是在一條條件的基礎上再匹配多另一條條件,有同學說直接Where(it=>it%2!==0||it>0)就可以了.必須指明的是,后者就變成了一個條件.你把兩個條件合并寫死成一個條件了.不是將其"組合"成一個新條件.就像你用樂高堆砌出一架跑車模型和直接澆鑄出一架跑車模型的概念是完全不同的.

      優雅實現

      雖然我們完美的實現了Specification模式,但是,聰明的你應該能看到它的弊病了.就是傳統的Specification模式實在是太"重量級"了,如果你想實現一個新的"規格",那么你必須需要新增一個新的Specification類.這樣下來,最終我們的類庫中必然堆積了許許多多的Specification類.既然如此,有沒有什么方法可以讓其的實現變得更加的輕易?答案是肯定的.我們再一次解析Specification模式,其重點是IsSatisfiedBy方法.遵守我們一貫的思路,改進必然是在重點實現處.于是,一種優雅的實現便誕生了.

          public interface ISpecification<T>
          {
      
              bool IsSatisfiedBy(T candidate);
      
          }

      我們還是必須定義一個ISpecification接口.與前面不同的是,該接口里不再有Add,Or,Not等方法.為何?后面講解.

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

      接下來,我們定義了Specification<T>類繼承了ISpecification<T>接口,此處要注意的是.在其構造函數中.我們傳入了一個委托,然后,將該委托賦給私有變量m_isSatisfiedBy,最后.IsSatisfiedBy方法只是簡單的調用了該Func,這實際上了也是依賴了注入.只不過我們注入的是一種特殊的類,委托.如此一來,只要我們需要新的"規格"時,只需要傳入相應不同委托便可以實現.那么傳統實現中Add,Or,Not等組合實現該如何實現.在次我們利用C#3.5的特性--擴展方法.我們實現了一個擴展類,并將所有的"組合"方法變成擴展方法.

          public static class SpecificationExtensions
          {
      
              public static ISpecification<T> Add<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));
      
              }
      
          }

      至于為什么要生成一個新的擴展類,并將方法提取出來.站在面向對象的角度上并不能說哪種更"面向對象",實際上,并沒有純粹意義上的"面向對象標準".只是我們習慣上會不知不覺把一些"良好的面向對象實踐"當成"標準",開發者站在不同的位置上,看到的東西,細節必然不同.如此,"面向對象"的結果也就不同.老趙說得很對(個人觀點),當我們執行Add,Or,Not等操作的時候,并不是對象本身去Add,Or,Not,一般比較而言,更多的我們不會拿自己與別人比較,這樣未免有失公正,而是有個"第三方",由它來進行比較,拿"你"和"他"進行比較.這里,我們也是借鑒現實生活的抽象,完成類的抽象.至此,這個輕量級的實現已經完成.

              static void Main(string[] args)
              {
      
                  var items = Enumerable.Range(-5, 10);
      
                  ISpecification<int> oddSpec = new Specification<int>(it => it % 2 != 0);
      
                  var spec = MoreCandidate(oddSpec);
      
                  foreach (var i in items.Where(it => spec.IsSatisfiedBy(it)))
                  {
      
                      Console.WriteLine(i);
      
                  }
      
              }
      
              static ISpecification<int> MoreCandidate(ISpecification<int> spec)
              {
      
                  ISpecification<int> plusSpec = new Specification<int>(it => it > 0);
      
                  return spec.Or(plusSpec);
      
              }

      clip_image004

      輕量級實現

      即使前面的實現已經足夠"輕量級",但對于懶人而言卻往往還是不夠的.那么是否還有更"懶"的實現方法?答案是肯定的.再一想一下,Specification模式的實現其實就是IsSatisfiedBy方法的實現.那么我們直接把IsSatisfiedBy提取出來,形成一種更"懶"的實現.聰明的你應該想到了.答案就是利用委托.我們新建了一個委托.

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

      命名為Spec完全只是為了說明這是一個Specification,它接受一個參數,并返回一個布爾值.只不過這種實現是在太過于簡單.簡單到沒有提供一定的約束.所以,必須遵守一種約定,這也是約定大于約束的一種實現.和第二種實現同理,我們還實現一個SpecificationExtension類.

          public static class SpecExtensitions
          {
      
              public static Spec<T> Add<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);
      
              }
      
          }

      這樣一來.我們就實現了一套"超輕量級"的Specification實現.

              static void Main(string[] args)
              {
      
                  var items = Enumerable.Range(-5, 10);
      
                  Spec<int> oddSpec = it => it % 2 != 0;
      
                  var spec = MoreCandidate(oddSpec);
      
                  foreach (var i in items.Where(it => spec(it)))
                  {
      
                      Console.WriteLine(i);
      
                  }
      
              }
      
              static Spec<int> MoreCandidate(Spec<int> spec)
              {
      
                  return spec.Or(it => it > 0);
      
              }

      結語

      Specification模式的應用能很大程度上減少我們的工作量,目前應用的比較多的是在LINQ2SQL上,查詢數據時采用不同的Specification從而獲取你所需要的數據.MVC下的Reposity+Specification能大大提高項目的擴展性.不過,世上沒有萬能的靈丹妙藥,如一把雙刃劍,能傷人,也能傷己.任何一種模式的濫用都會造成不良的影響.所以,只有該需要它的時候使用它才是最合理的.那什么時候該使用呢?當你發現你的條件實在是太過千變萬化,當你需要OrWhere,當你.....(歡迎你留下你認為合適的時候,:-) )

      擴展閱讀

      Specification模式

      依賴注入(控制反轉)

      趣味編程:C#中Specification模式的實現

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

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

      主站蜘蛛池模板: 中文人妻av高清一区二区| 国产成人av大片大片| 成人麻豆日韩在无码视频| 精品国产这么小也不放过| 国产麻豆精品一区一区三区| 国产精品久久久久久无毒不卡| 国产亚洲精品AA片在线爽| 亚洲国产精品第一二三区| 国产精品视频午夜福利| 午夜一区二区三区视频| 无码国模国产在线观看免费| 亚洲人成网站观看在线观看| 久久99精品久久久久久齐齐| 欧美视频二区欧美影视| 你懂的亚洲一区二区三区| 无遮无挡爽爽免费视频| 人妻体内射精一区二区三区| 欧美乱码卡一卡二卡四卡免费| 国产极品尤物粉嫩在线观看| 久青草国产综合视频在线| 人妻无码不卡中文字幕系列| 熟女一区二区中文字幕| 毛片av在线尤物一区二区 | 久久综合五月丁香六月丁香| 亚洲国产初高中生女av| 天天躁日日躁狠狠躁中文字幕| 精品午夜福利短视频一区| 国产老妇伦国产熟女老妇高清| 国产成人a∨激情视频厨房| 青青青国产在线观看免费| 亚洲国产精品综合久久20| 欧美亚洲h在线一区二区| 亚洲伊人五月丁香激情| 久久中文骚妇内射| 视频一区二区三区刚刚碰 | 亚洲国产午夜精品福利| 欧洲码亚洲码的区别入口| 国产二区三区不卡免费| 五华县| 亚洲乱色一区二区三区丝袜| 亚洲午夜无码久久久久蜜臀AV|