当模板方法遇到了委托函数,你的代码又可以精简了
现如今当你翻看一些开源项目源码的时候,你会发现现在到处充斥着委托函数,如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 Proce***equest() { 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 Proce***equest() { base.Proce***equest(); } } class LianheweituoTemplate : MmsTemplate { public override string GetHeader() { return "我是联合维拓头!"; } public override string GetTail() { return "我是联合维拓体!"; } public override string GetBody() { return "我是联合维拓尾!"; } public override void Proce***equest() { base.Proce***equest(); } }
然后客户端可以根据指定通道配置调用相应的子类实现不同厂家的彩信体构建。
二:委托函数
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 Proce***equest() { Console.WriteLine($"1. 彩信头:{header()}"); Console.WriteLine($"2. 彩信体:{header()}"); Console.WriteLine($"3. 彩信尾:{tail()}"); } } class ZhutongTemplate : MmsTemplate { public override void Proce***equest() { this.header = () => "我是助通头!"; this.body = () => "我是助通体"; this.tail = () => "我是助通尾!"; base.Proce***equest(); } } class LianheweituoTemplate : MmsTemplate { public override void Proce***equest() { this.header = () => "我是联合维拓头!"; this.body = () => "我是联合维拓体"; this.tail = () => "我是联合维拓尾!"; base.Proce***equest(); } }
从上面代码中可以看到,原来需要多态实现的地方直接由委托变量接管,看起来是不是比之前的多态版简洁了很多。
好了,本篇就说到这里,更多的变通玩法期待您的发现~
- 当模板方法遇到了委托函数,你的代码又可以精简了
- 写代码要精简,可以一个方法实现的就不要用两个方法去实现,努力!
- thinkphp在前端页面的js代码中可以使用 U方法吗? 可以使用模板变量如__URL__等吗?
- 精简代码:Python的split方法函数可以分割字符串成列表,默认是以空格作为分隔符sep来分割字符串。
- freemarker 替换字符串,模板,可以用来动态生成代码
- dedecms模板内加入php代码的方法
- IntelliJ2017:如何将一段代码变成可以便捷输入的模板
- 代码精简的可以实现元素圆角的js函数
- 国际:写出漂亮代码的七种方法----看了美化化码的想法,觉得很好,故加以引用,希望更多人可以看到
- ubuntu 12.04(gcc降级)编译android代码遇到"_FORTIFY_SOURCE"的解决方法
- JDBC之使用策略模式和模板方法模式优化代码
- 图文描述Vs2005制作WEB应用程序安装包的方法[E8.Net正式用户可以找我们获取全部代码参考]
- 除了写代码之外,一直想找个时间记录下自己在工作中遇到问题,和一些解问题的方法,毕竟也在不断的成长每次回头看看自己写的,都会有不同的感悟
- 快看,这里有个简单的方法可以测某段代码的运行时间
- 《Thinking in Java》RMI远程方法示例代码运行是可能遇到的问题及解决方法
- 代码添加 GridView 模板列一种方法示例
- ubuntu 12.04(gcc降级)编译android代码遇到"_FORTIFY_SOURCE"的解决方法
- Android APK反编译方法(可以获取APK xml和android Manifest,java代码等内容)
- 求一段代码运行时所花费的时间(模板设计方法设计模式)
- 阅读layim代码小记,实现可以更改用户签名的方法