當模板方法遇到了委託函數,你的代碼又可以精簡了
- 2020 年 4 月 12 日
- 筆記
現如今當你翻看一些開源項目源碼的時候,你會發現現在到處充斥着委託函數,如Func,Action,Predicate,確實現在的C#在函數式編程的路上越來越成為主流,越來越顯示威力,曾經的一些經典設計模式寫法,在函數式下可以稍微優化一下了,這篇我們就來說說模板方法。
一:實際場景
1. 模板方法定義
相信這個模式在平時開發中會經常使用到,定義也很簡單,在父類中定義算法骨架,骨架裏面的某些細節點由相應的子類實現。
2. 業務場景
給用戶推送彩信的時候,公司需要對接很多的彩信服務商,比如說博士通,助通,聯合維拓,而每一家對提交彩信的格式有不同的要求,比如說:博士通和助通會要求所有的內容按指定格式進行base64編碼提交過去,聯合維拓會要求你按指定格式打包成一個zip文件流過去,這就是一個經典的模板模式,可以在父類中定義好構造彩信的算法骨架,具體細節可以由各自廠家子類實現,為了方便演示畫圖如下:
源碼如下:
class MmsTemplate { public virtual string GetHeader() { return string.Empty; } public virtual string GetBody() { return string.Empty; } public virtual string GetTail() { return string.Empty; } public virtual void ProcessRequest() { Console.WriteLine($"1. 彩信頭:{GetHeader()}"); Console.WriteLine($"2. 彩信體:{GetBody()}"); Console.WriteLine($"3. 彩信尾:{GetTail()}"); } } class ZhutongTemplate : MmsTemplate { public override string GetHeader() { return "我是助通頭!"; } public override string GetTail() { return "我是助通體!"; } public override string GetBody() { return "我是助通尾!"; } public override void ProcessRequest() { base.ProcessRequest(); } } class LianheweituoTemplate : MmsTemplate { public override string GetHeader() { return "我是聯合維拓頭!"; } public override string GetTail() { return "我是聯合維拓體!"; } public override string GetBody() { return "我是聯合維拓尾!"; } public override void ProcessRequest() { base.ProcessRequest(); } }
然後客戶端可以根據指定通道配置調用相應的子類實現不同廠家的彩信體構建。
二:委託函數
1. 反思
在面向對象編程語言中,這種寫法都堪稱標準,我們先來捋一下流程,子類入口 -> 執行父類方法 -> 調用子類方法 如下圖
從上圖中可以發現一個問題,父類在執行算法骨架的時候,為了能夠再次執行到該子類方法,在面向對象編程中必須要使用的技術就是多態,而為了構造多態,就必須在父類中定義一堆方法,然後由子類實現這一堆方法,這就是你看到的GetHeader(),GetTail(),GetBody()的由來,這時就顯得有點老態龍鍾。
2. 回調函數
仔細看一下這個xmind圖,ZhutongTemplate類調用的MmsTemplate的方法,MmsTemplate在執行的時候再調用ZhutongTemplate的方法,前者叫調用,後者叫回調,如果還不明白,那前者叫送禮,後者叫回禮。。。 對,既然在以前是用多態製造回調,那我是不是可以直接使用C#中的委託函數更簡單粗暴呢?
3. 改造模板
直接看代碼吧,千言難抵上代碼。
class MmsTemplate { protected Func<string> header; protected Func<string> body; protected Func<string> tail; public virtual void ProcessRequest() { Console.WriteLine($"1. 彩信頭:{header()}"); Console.WriteLine($"2. 彩信體:{header()}"); Console.WriteLine($"3. 彩信尾:{tail()}"); } } class ZhutongTemplate : MmsTemplate { public override void ProcessRequest() { this.header = () => "我是助通頭!"; this.body = () => "我是助通體"; this.tail = () => "我是助通尾!"; base.ProcessRequest(); } } class LianheweituoTemplate : MmsTemplate { public override void ProcessRequest() { this.header = () => "我是聯合維拓頭!"; this.body = () => "我是聯合維拓體"; this.tail = () => "我是聯合維拓尾!"; base.ProcessRequest(); } }
從上面代碼中可以看到,原來需要多態實現的地方直接由委託變量接管,看起來是不是比之前的多態版簡潔了很多。
好了,本篇就說到這裡,更多的變通玩法期待您的發現~