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

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


©著作权归作者所有:来自51CTO博客作者mb5fd86a704dffe的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 怎么理解java的面向对象及三个特性
  2. php学习笔记(类声明,类的实例化,类的静态成员与类的扩展)
  3. 面向对象封装,继承,加载器
  4. 接口和抽象类
  5. Java基础知识点1
  6. Android的Activity的启动流程分析
  7. android的一些知识小记
  8. FragmentPagerAdapter API
  9. Android中进入页面默认定位到ListView的第一条数据解决方法

随机推荐

  1. Android各版本及API对应关系,持续更新!
  2. IIS7上设置MIME让其支持android和Iphone
  3. 去除安卓checkbox按下时的阴影效果
  4. Android ORM系列之ActiveAndroid
  5. java.lang.IllegalStateException: You n
  6. android开发01 --开发工具
  7. Android开发中 AndroidManifest.xml配置
  8. 【LatinIME】默认开启键盘按键声
  9. Android(安卓)Gallery3D效果 教程 案例
  10. android中string.xml文件的使用