規(guī)范模式-------FromABPDocument

    

成都一家集口碑和實力的網(wǎng)站建設(shè)服務商,擁有專業(yè)的企業(yè)建站團隊和靠譜的建站技術(shù),十載企業(yè)及個人網(wǎng)站建設(shè)經(jīng)驗 ,為成都數(shù)千家客戶提供網(wǎng)頁設(shè)計制作,網(wǎng)站開發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務,包括成都營銷型網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),同時也為不同行業(yè)的客戶提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)的服務,包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務商就選創(chuàng)新互聯(lián)建站

介紹

規(guī)范模式是一種特定的軟件設(shè)計模式,通過使用布爾邏輯 (維基百科)將業(yè)務規(guī)則鏈接在一起,可以重新組合業(yè)務規(guī)則。

在實際中,它主要用于 為實體或其他業(yè)務對象定義可重用的過濾器。

在本節(jié)中,我們將看到需要規(guī)格模式。本節(jié)是通用的,與ABP的實現(xiàn)無關(guān)。

假設(shè)您有一種服務方法來計算客戶的總數(shù),如下所示:

 規(guī)范模式-------From ABP Document

public  class CustomerManager
{    public  int  GetCustomerCount()
    {        // TODO ... 
        return  0 ;
    }
}

 規(guī)范模式-------From ABP Document

 

您可能希望通過過濾器獲得客戶數(shù)量。例如,您可能會有高級客戶(其余額超過10萬美元),或者您可能想要通過 注冊年度過濾客戶。然后,您可以創(chuàng)建其他方法,如GetPremiumCustomerCount(), GetCustomerCountRegisteredInYear(int year) GetPremiumCustomerCountRegisteredInYear(int year)等。由于您有更多的標準,因此無法為每種可能性創(chuàng)建組合。

這個問題的一個解決方案是規(guī)范模式。我們可以創(chuàng)建一個獲取參數(shù)作為過濾器的方法

 規(guī)范模式-------From ABP Document

public class CustomerManager
{    private readonly IRepository<Customer> _customerRepository;    public CustomerManager(IRepository<Customer> customerRepository)
    {
        _customerRepository = customerRepository;
    }    public int GetCustomerCount(ISpecification<Customer> spec)
    {        var customers = _customerRepository.GetAllList();        var customerCount = 0;        
        foreach (var customer in customers)
        {            if (spec.IsSatisfiedBy(customer))
            {
                customerCount++;
            }
        }        return customerCount;
    }
}

 規(guī)范模式-------From ABP Document

 

因此,我們可以獲得任何對象作為實現(xiàn) ISpecification <Customer>接口的參數(shù),定義如下:

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

 

 

我們可以與客戶一起致電IsSatisfiedBy,以測試該客戶是否有意。因此,我們可以使用相同的GetCustomerCount與不同的過濾器,而不改變方法本身。

雖然這個解決方案在理論上是相當不錯的,但應該改進,以更好地在C#中工作。例如,它是沒有效率得到所有客戶提供從數(shù)據(jù)庫來檢查它們是否滿足給定的規(guī)格/條件。在下一節(jié)中,我們將看到ABP的實現(xiàn),克服了這個問題。

創(chuàng)建規(guī)范類

ABP定義了ISpecification界面,如下所示:

 規(guī)范模式-------From ABP Document

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

    Expression<Func<T, bool>> ToExpression();
}

 規(guī)范模式-------From ABP Document

 

 

添加ToExpression()方法,該方法返回一個表達式,并用于更好地與IQueryable和 Expression樹的集成。因此,我們可以輕松地將規(guī)范傳遞給存儲庫,以在數(shù)據(jù)庫級別應用過濾器。

我們通常從規(guī)范<T>類繼承,而不是直接實現(xiàn)ISpecification <T>接口。規(guī)范類自動實現(xiàn)IsSatisfiedBy方法。所以,我們只需要定義ToExpression。我們來創(chuàng)建一些規(guī)范類:

 規(guī)范模式-------From ABP Document

//Customers with $100,000+ balance are assumed as PREMIUM customers.public class PremiumCustomerSpecification : Specification<Customer>{    public override Expression<Func<Customer, bool>> ToExpression()
    {        return (customer) => (customer.Balance >= 100000);
    }
}//A parametric specification example.public class CustomerRegistrationYearSpecification : Specification<Customer>{    public int Year { get; }    public CustomerRegistrationYearSpecification(int year)
    {
        Year = year;
    }    public override Expression<Func<Customer, bool>> ToExpression()
    {        return (customer) => (customer.CreationYear == Year);
    }
}

 規(guī)范模式-------From ABP Document

 

 

如你所見,我們只是實現(xiàn)了簡單的lambda表達式 來定義規(guī)范。讓我們使用這些規(guī)格來獲得客戶數(shù)量:

count = customerManager.GetCustomerCount(new PremiumCustomerSpecification());
count = customerManager.GetCustomerCount(new CustomerRegistrationYearSpecification(2017));

 

使用規(guī)范與存儲庫

現(xiàn)在,我們可以優(yōu)化 CustomerManager 在數(shù)據(jù)庫中應用過濾器

 規(guī)范模式-------From ABP Document

public class CustomerManager
{    private readonly IRepository<Customer> _customerRepository;    public CustomerManager(IRepository<Customer> customerRepository)
    {
        _customerRepository = customerRepository;
    }    public int GetCustomerCount(ISpecification<Customer> spec)
    {        return _customerRepository.Count(spec.ToExpression());
    }
}

 規(guī)范模式-------From ABP Document

 

 

這很簡單 我們可以將任何規(guī)范傳遞給存儲庫,因為 存儲庫可以使用表達式作為過濾器。在此示例中,CustomerManager是不必要的,因為我們可以直接使用具有規(guī)范的存儲庫來查詢數(shù)據(jù)庫。但是認為我們想對一些客戶執(zhí)行業(yè)務操作。在這種情況下,我們可以使用具有域服務的規(guī)范來指定客戶進行工作。

撰寫規(guī)格

規(guī)格一個強大的功能是,它們可組合使用 AND,OR,不ANDNOT擴展方法。例:

var count = customerManager.GetCustomerCount(new PremiumCustomerSpecification().And(new CustomerRegistrationYearSpecification(2017)));

 

 

我們甚至可以從現(xiàn)有規(guī)范中創(chuàng)建一個新的規(guī)范類:

 規(guī)范模式-------From ABP Document

public class NewPremiumCustomersSpecification : AndSpecification<Customer>{    public NewPremiumCustomersSpecification() 
        : base(new PremiumCustomerSpecification(), new CustomerRegistrationYearSpecification(2017))
    {
    }
}

 規(guī)范模式-------From ABP Document

 

 

規(guī)范Specification 類的一個子類,只有在兩個規(guī)范都滿足的時候才能滿足。那么我們可以像其他規(guī)格一樣使用NewPremiumCustomersSpecification:

var count = customerManager.GetCustomerCount(new NewPremiumCustomersSpecification());

 

 

討論

雖然規(guī)范模式比C#lambda表達式更早,但它通常與表達式進行比較。一些開發(fā)者可能會認為它不再需要,我們可以直接將表達式傳遞到存儲庫或域服務,如下所示:

var count = _customerRepository.Count(c => c.Balance > 100000 && c.CreationYear == 2017);

 

 

由于ABP的存儲庫支持expessions,這是完全有效的用法。您不必在應用程序中定義或使用任何規(guī)范,您可以使用表達式。那么說明什么呢?為什么和何時應該考慮使用它們?

何時使用?

使用規(guī)格的一些好處:

  • Reusabe:認為您需要在您的代碼庫中的許多地方使用PremiumCustomer過濾器。如果您使用表達式而不是創(chuàng)建規(guī)范,如果您以后更改“高級客戶”定義(例如,要將最終余額從100,000美元更改為25萬美元,并添加另一個條件,以成為3歲以上的客戶),會發(fā)生什么。如果您使用規(guī)范,您只需更改單個類。如果您使用(復制/粘貼)相同的表達式,則需要更改它們。

  • 可組合:您可以將多個規(guī)格來創(chuàng)建新的規(guī)范。這是另一種可重用性。

  • 命名:PremiumCustomerSpecification更好地解釋了意圖,而不是復雜的表達。因此,如果您的業(yè)務有意義的表達式,請考慮使用規(guī)范。

  • 可測試:一個規(guī)范是單獨(和容易)可測試的對象。

何時不使用?
  • 非業(yè)務表達式:您可以考慮不使用非業(yè)務相關(guān)表達式和操作的規(guī)范。

  • 報告:如果你只是創(chuàng)建一個報表,不要創(chuàng)建規(guī)范,而是直接使用IQueryable。實際上,您甚至可以使用簡單的SQL,Views或其他工具進行報告。DDD不關(guān)心報告,并且從性能的角度來看,底層數(shù)據(jù)存儲的查詢優(yōu)勢可能很重要。

當前名稱:規(guī)范模式-------FromABPDocument
轉(zhuǎn)載來于:http://muchs.cn/article38/jepipp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化網(wǎng)站收錄、定制開發(fā)建站公司、動態(tài)網(wǎng)站、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)