規約模式允許我們將一小塊領域知識封裝到乙個單元中,即規約,然後可以在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.利用覆蓋索引來進行查詢操作,避免...