现如今当你翻看一些开源项目源码的时候,你会发现现在到处充斥着委托函数,如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();}}

从上面代码中可以看到,原来需要多态实现的地方直接由委托变量接管,看起来是不是比之前的多态版简洁了很多。

好了,本篇就说到这里,更多的变通玩法期待您的发现~

当模板方法遇到了委托函数,你的代码又可以精简了相关推荐

  1. 利用BP神经网络教计算机进行非线函数拟合(代码部分多层)

    利用BP神经网络教计算机进行非线函数拟合(代码部分多层) 本图文已经更新,详细地址如下: http://blog.csdn.net/lsgo_myp/article/details/54425751

  2. R语言使用tryCatch函数调试R代码实战:tryCatch函数运行正常R代码、tryCatch函数运行有错误(error)的R代码示例/tryCatch函数运行有警告(warning)的R代码示例

    R语言使用tryCatch函数调试R代码实战:tryCatch函数运行正常R代码.tryCatch函数运行有错误(error)的R代码示例/tryCatch函数运行有警告(warning)的R代码示例 ...

  3. C# 四舍五入round函数使用的代码

    下边资料是关于C# 四舍五入round函数使用的代码,希望能对大家有一些用处. using System;public class Example {public static void Main() ...

  4. 用Async函数简化异步代码

    Promise 在 JavaScript 上发布之初就在互联网上流行了起来 - 它们帮开发人员摆脱了回调地狱,解决了在很多地方困扰 JavaScript 开发者的异步问题.但 Promises 也远非 ...

  5. ML之ME/LF:基于不同机器学习框架(sklearn/TF)下算法的模型评估指标(损失函数)代码实现及其函数(Scoring/metrics)代码实现(仅代码)

    ML之ME/LF:基于不同机器学习框架(sklearn/TF)下算法的模型评估指标(损失函数)代码实现及其函数(Scoring/metrics)代码实现(仅代码) 目录 单个评价指标各种框架下实现 1 ...

  6. f2py支持在fortran语言中调用其他Fortran函数或C代码或Python代码

    f2py支持在fortran语言中调用其他Fortran函数或C代码或Python代码 分类: Python Numpy_Scipy fortran MinGW_GCC_Boost f2py 2012 ...

  7. 将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中

    将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中 写这种.h和.cpp文件分开的大程序,虽然对很多人来说很简单,对自己来说算是第一次吧,好好学C++,加油~ 题目:定义Point类,由 ...

  8. android 揭示动画_如何使用意图揭示函数名称使代码更好

    android 揭示动画 Discover Functional JavaScript was named one of the best new Functional Programming boo ...

  9. php datediff 函数,dateAdd与DateDiff函数的js代码

    1.DateAdd函数: 复制代码 代码示例: function DateAdd(interval,number,date){ switch(interval.toLowerCase()){ case ...

最新文章

  1. 【Linux】一步一步学Linux——dig命令(160)
  2. 用wubi在一个独立分区硬件装ubuntu12.04产生的无法识别U盘的解决办法
  3. log4j debug写法
  4. CUL8R的完整形式是什么?
  5. Android Studio导入project和module的方法
  6. Spring Boot基础学习笔记18:Spring Boot整合Redis缓存实现
  7. python对比图片
  8. AOP 拦截器 JDK动态代理机制 struts2 mybatis spring-aop
  9. 如何解决: ModuleNotFoundError: No module named ‘object_detection‘
  10. php设置编程,php – 以编程方式设置基本图像
  11. GitHub星标数超4.2万的火爆之作!
  12. 【通信仿真】基于matlab V-BLAST结构检测算法仿真【含Matlab源码 1683期】
  13. 输入输出练习 python
  14. linux 光标切换快捷键,光标操作快捷键,光标快捷键
  15. 防火墙技术及应用(一)
  16. Java基础部分 阶段一(语法基础)1、开发环境搭建(计算机编程及开发语言)
  17. 听书笔记:《勇敢去敲老板的门》
  18. 海康大华硬件NVR如何配置接入GB/T28181国标流媒体平台说明及示例
  19. 简单模拟word中对插入直线的操作
  20. 圆锥曲线条件4a3+27b2 !=0

热门文章

  1. # javascript 总结
  2. 父元素 高度固定,如何使其中的文字垂直居中?
  3. 猎豹MFC--CMenu菜单 设置主菜单 给主对话框设置菜单 设置快捷菜单
  4. Oracle B-Tree Index 原理
  5. 短语密码_使用密码短语以提高安全性
  6. 物体成瘾性_科技成瘾使我们不那么快乐。 那是一个市场机会。
  7. ad中电源插座怎么封装_您可以在房屋中安装的各种电源插座
  8. sketch怎么移动图层_什么是Photoshop Express,Fix,Mix和Sketch移动应用程序?
  9. 如何使用oracle查询,oracle 表查询
  10. AWD-LSTM为什么这么棒?