使用过滤器模式,让客户关怀中的代码更加干净整洁
一:實際場景介紹
我們在給用戶做訂單催付通知的時候,會有這樣的一種場景,用戶在系統后臺設置一組可以催付的規則,比如說訂單金額大于xx元,非黑名單用戶,來自哪個地區,已購買過某個商品,指定某個營銷活動的人等等這樣的條件,如果這時用戶在淘寶上下了一個訂單,那程序要判斷的就是看一下此訂單是否滿足這些規則中的某一個,如果滿足,我們給他發送催付通知,這種場景是很多做CRM的同學都會遇到的問題,那針對這種場景,如何更好的規劃業務邏輯呢?
二:普通的編程代碼
在這里我們就不考慮多篩選條件下的性能,而只從代碼維護復雜度考慮,如果不清楚設計模式的同學,大概會寫出如下的代碼:
namespace ConsoleApplication1 {class Program{static void Main(string[] args){var regulars = new List<Regulars>();regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則1", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則2", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則3", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則4", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則5", AnalysisConditons = "xxxx" });var filters = FilterRegularID(regulars);filters = FilterRegularName(filters);filters = FilterCondtions(filters);//... 后續邏輯}static List<Regulars> FilterRegularID(List<Regulars> persons){//過濾 “姓名” 的邏輯return null;}static List<Regulars> FilterRegularName(List<Regulars> persons){//過濾 “age” 的邏輯return null;}static List<Regulars> FilterCondtions(List<Regulars> persons){//過濾 “email” 的邏輯return null;}}/// <summary>/// 各種催付規則/// </summary>public class Regulars{public int RegularID { get; set; }public string RegularName { get; set; }public string AnalysisConditons { get; set; }} }為了演示,上面的代碼是從?regularid,regularname,condition?三個維度對 regulars 這個聚合對象進行AND模式的篩選過濾,當過濾維度比較多的時候,這種寫法看的出來是簡單粗暴,維護起來也必須簡單粗暴, 所以上萬行代碼也就是這么出來的,設計模式告訴我們一個簡單的“開閉原則”,那就是追求最小化的修改代碼,這種場景有更好的優化策略嗎?對應到設計模式上就是 “過濾器模式”, 專門針對這種場景的解決方案,一個維度一個類,然后通過邏輯運算類將他們進行組合,可以看出這是一種“結構式的設計模式”。
三:過濾器模式
好了,廢話不多說,先來看一下優化后的設計圖紙如下:
從上面這張圖紙中可以看到,我已經將三個維度的過濾方法提取成了三個子類,由此抽象出了一個IFilter接口,當然你也可以定義成抽象類,然后實現了兩個運算級 AND 和 OR 子類Filter,用于動態的對原子性的?RegularIDFilter,RegularNameFilter,ReuglarCondtionFilter?進行 AND,OR 邏輯運算,下面我們再看具體代碼:
1. IFilter
public interface IFilter{List<Regulars> Filter(List<Regulars> regulars);}2. RegularIDFilter
public class RegularIDFilter : IFilter{/// <summary>/// Regulars的過濾邏輯/// </summary>/// <param name="regulars"></param>/// <returns></returns>public List<Regulars> Filter(List<Regulars> regulars){return null;}}3.RegularNameFilter
public class RegularNameFilter : IFilter{/// <summary>/// regularName的過濾方式/// </summary>/// <param name="regulars"></param>/// <returns></returns>public List<Regulars> Filter(List<Regulars> regulars){return null;}}4. RegularCondtionFilter
public class RegularCondtionFilter : IFilter{/// <summary>/// Condition的過濾條件/// </summary>/// <param name="regulars"></param>/// <returns></returns>public List<Regulars> Filter(List<Regulars> regulars){return null;}}5. AndFilter
/// <summary>/// filter的 And 模式/// </summary>public class AndFilter : IFilter{List<IFilter> filters = new List<IFilter>();public AndFilter(List<IFilter> filters){this.filters = filters;}public List<Regulars> Filter(List<Regulars> regulars){var regularlist = new List<Regulars>(regulars);foreach (var criteriaItem in filters){regularlist = criteriaItem.Filter(regularlist);}return regularlist;}}6. OrFilter
public class OrFilter : IFilter{List<IFilter> filters = null;public OrFilter(List<IFilter> filters){this.filters = filters;}public List<Regulars> Filter(List<Regulars> regulars){//用hash去重var resultHash = new HashSet<Regulars>();foreach (var filter in filters){var smallPersonList = filter.Filter(regulars);foreach (var small in smallPersonList){resultHash.Add(small);}}return resultHash.ToList();}}7. 最后我們客戶端調用程序就簡單了,只要將“原子性”的過濾條件追加到“邏輯運算類”中就完美了,如下圖:
class Program{static void Main(string[] args){var regulars = new List<Regulars>();regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則1", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則2", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則3", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則4", AnalysisConditons = "xxxx" });regulars.Add(new Regulars() { RegularID = 1, RegularName = "規則5", AnalysisConditons = "xxxx" });//追加filter條件var filterList = new IFilter[3] {new RegularIDFilter(),new RegularNameFilter(),new RegularCondtionFilter()};var andCriteria = new AndFilter(filterList.ToList());//進行 And組合 過濾andCriteria.Filter(regulars);}}當你仔細看完上面的代碼,會不會發現,如果后續有需求變更,比如說增加篩選的維度,我只需要新增一個繼承 IFilter 的子類就搞定了,客戶端在調用的時候只要在Filters集合中追加該篩選維度,是不是就OK了,所以這種模式幾乎達到了無代碼修改的地步~~~好了,本篇就說到了這里,希望對你有幫助~
總結
以上是生活随笔為你收集整理的使用过滤器模式,让客户关怀中的代码更加干净整洁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 认证授权方案之JwtBearer认证
- 下一篇: Webapi管理和性能测试工具WebBe