規約模式Specification Pattern

2022-03-31 01:12:54 字數 2730 閱讀 7276

規約模式允許我們將一小塊領域知識封裝到乙個單元中,即規約,然後可以在code base中對其進行復用。

它可以用來解決在查詢中氾濫著getbysomething方法的問題,以及對查詢條件的組合和復用。

舉個例子

public class movie : entity

public datetime releasedate

public mpaarating mpaarating

public string genre

public double rating

}public enum mpaarating

這樣如果按不同的條件來查詢,就會出現如下**

public class movierepository

public ireadonlylistgetbyrating(double minrating)

public ireadonlylistgetbygenre(string genre)

}

如果我們想要根據多個條件來查詢情況就會變得稍微負責一點,如下

public class movierepository

}

而且有時,我們需要在記憶體中篩選資料,有時我們需要在sql中篩選資料,這樣就會出現如下兩種寫法

//記憶體中篩選資料

public result buychildticket(int movieid)

//資料庫中篩選資料

public class movierepository

}

這樣子就違反了dry原則,因為領域相關的資訊(兒童電影)就出現在了兩個位置。此時,我們可以通過規約模式來解決該問題。我們引入乙個新的類來去甄別不同型別的電影。

這樣不僅移除了重複的領域資訊,還可以組合多個規約。

規約模式可以在如下三個場景使用

首先給出最原始的實現方式。這種方式依賴於c#的expression。如下(這也是目前我在專案直接想到使用的方式)

// controller

public void somemethod()

// repository

public ireadonlylistfind(expression> expression)

這種方式,解決了getbysomething的情況,但是領域資訊是不能復用的。m => m.mpaarating == mpaarating.g這樣的**可能會在應用中被複製多次。

一種改進的實現方式,是使用泛型規約類,如下。

public class genericspecification

public genericspecification(expression> expression)

public bool issatisfiedby(t entity)

}public void somemethod()

public ireadonlylistfind(genericspecificationspecification)

這裡呢,問題依然如上,仍舊沒解決m => m.mpaarating == mpaarating.g不方便復用。

這種方式,我們將領域資訊硬編碼進規約內,外部不能或者不太可能改變。

public abstract class specification

}public class mpaaratingatmostspecification : specification

public override expression> toexpression()

}

這樣我們使得領域資訊更容易復用,而且在建立其他規約時,也不需要重複原來的規約。而且非常方便對規約進行組合,如and、or和not。如下

public abstract class specification

// and also or and not methods

}public class andspecification: specification

public override expression> toexpression()

}//如下擴充套件方法,是用來處理andalso中的表示式樹引數的

public static class expressionext

// otherwise, keep expr1 "as is" and invoke expr2

return expression.lambda>(

expression.andalso(

expr1.body,

expression.invoke(expr2, param)), param);

}}

這樣,我們就可以組合規約了,如下

var grating = new mpaaratingatmostspecification(mpaarating.g);

var goodmovie = new goodmoviespecification();

var repository = new movierepository();

ireadonlylistmovies = repository.find(grating.and(goodmovie));

規約模式學習總結

目前想到的可以使用規約模式的情況 以後想到了再補充 1.當有一組條件,被多處使用,且這些條件可以任意組合時,這個時候考慮使用規約模式來解耦 下面看一下規約模式的簡單實現 public inte ce ispecificationwhere t class public abstract class ...

DDD 領域服務的規約模式

回到目錄 規 約 specification 模式 第一次看到這東西是在microsoft nlayer專案中,它是微軟對ddd的解說,就像petshop告訴了我們mvc如何使用一樣,這個規約模式最重要的作用是實現了查詢語句與查詢條件的 分離,查詢語句在底層是穩定的,不變的,而查詢條件是和具體業務,...

編碼規約之索引規約

目錄 一 強制 1.業務上具有唯一特性的字段,即使是多個欄位的組合,也必須建成唯一索引 2.超過三個表禁止 join 3.在 varchar 欄位上建立索引時注意項 4.頁面搜尋嚴禁左模糊或者全模糊 二 推薦 1.如果有 order by 的場景注意索引的有序性 2.利用覆蓋索引來進行查詢操作,避免...