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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法--面试必问AVL树原理及实现

数据结构与算法–AVL树原理及实现 AVL&#xff08;Adelson-Velskii 和landis&#xff09;树是带有平衡条件的二叉查找树&#xff0c;这个平衡条件必须容易实现&#xff0c;并且保证树的深度必须是O(logN)。因此我们让一棵AVL树中每个节点的左子树和右子树的高度最多相差1&…

MySQL8.0新特性

在这之前Mysql的版本是5.7&#xff0c;也是目前使用最广泛的一个版本。现在新版本跳过了6和7直接来到了8&#xff0c;那么V6和V7版本去哪里了呢&#xff1f;比较靠谱的说法是v6用作了内部的其他用途而v7的话是因为mysql有个产品叫做clusterdb他有7这个版本&#xff0c;所以这个…

数据结构与算法--B树原理及实现

B树 前几篇文中讨论的数据结构我们都是假设所有的数据都存储在计算机的主存中。可说总要那么海量的数据需要通过个中数据结构去存储&#xff0c;我们不可能有这么多内存区存放这些数据。那么意味着我们需要将他们放磁盘。所以这个时候范问时间复杂度O决定了他是否能适合存储磁盘…

[C++STL]C++实现priority_queue容器适配器

代码如下: #pragma once #include <iostream> #include <vector> using namespace std;template<typename T> struct Less {bool operator()(const T &a, const T &b){return a < b;} };template<typename T> struct Greater {bool operat…

为什么要用内插字符串代替string.format

知道为什么要用内插字符串&#xff0c;只有踩过坑的人才能明白&#xff0c;如果你曾今使用string.format超5个以上占位符&#xff0c;那其中的痛苦我想你肯定是能够共鸣的。一&#xff1a;痛苦经历先上一段曾今写过的一段代码&#xff0c;大家来体会一下&#xff1a;LogHelper.…

SpringCloud Alibaba 框架下公司架构图

上一篇&#xff1a;Docker容器实战思维 下一篇&#xff1a;分布式事务理论模型

C++ 实现堆

代码如下(小根堆): #include <iostream> #include <assert.h> using namespace std;//小根堆,堆排序从大到小排 class Heap { public:Heap():data(nullptr), size(0), capacity(0) {}~Heap(){delete[] data;data nullptr;size 0;capacity 0;}/*void Swap(int *…

iPhone上运行Linux也要来了

FOSSBRTES 报道称&#xff0c;用户很快将可以通过双启动功能&#xff0c;像在 Android 设备上那样在 iPhone 上运行 Linux。目前&#xff0c;iOS 越狱极客、开发人员 Raffaele 以及 mcg29 已在其 Github 页面上发布了详细说明&#xff0c;详细介绍了如何双启动 64 位 iOS 设备。…

数据结构与算法--图论,最短路算法,拓扑排序算法

图论若干定义 图&#xff08;graph&#xff09;G&#xff08;V,E&#xff09;由定点vertex的集合V&#xff0c; 和边edge的集合E组成。每一条边都是一个点对点&#xff08;v&#xff0c;w&#xff09;&#xff0c;其中 v,w 属于V集合的子集 如果点对点 是有序的&#xff0c;那…

谁说.NET不适合搞大数据、机器学习和人工智能

SciSharp StackSciSharp STACK: https://scisharp.github.io/SciSharp/基于.NET的开源生态系统&#xff0c;用于数据科学、机器学习和AI。SciSharp将所有主要的ML/AI框架从Python引入.NET.特点为.NET开发者.NET开发者使用他们所了解和喜爱的工具可以最高效的工作。我们的使命是…

C++ 泛型编程 实现红黑树RBTree

代码如下: #include <iostream> #include <ctime> using namespace std;enum COLOR {BLACK,RED };template<typename T> struct RBTreeNode {RBTreeNode<T> * _parent;RBTreeNode<T> * _left;RBTreeNode<T> * _right;T _val;COLOR _color…

数据结构与算法--图论-深度优先搜索及其应用

深度优先搜索 深度优先搜索&#xff08;depth-first search&#xff09; 是对先序遍历&#xff08;preorder traversal&#xff09;的推广&#xff0c;我们从某个顶点v开始处理v&#xff0c;然后递归的遍历所有与v邻接顶点。如果这个过程是对一棵树进行&#xff0c;那么&#…

.NET Core技术研究-主机

前一段时间&#xff0c;和大家分享了 ASP.NET Core技术研究-探秘Host主机启动过程但是没有深入说明主机的设计。今天整理了一下主机的一些知识&#xff0c;结合先前的博文&#xff0c;完整地介绍一下.NET Core的主机的设计和构建启动过程。一、什么是主机主机是一个封装了应用资…

数据结构与算法--贪婪算法

贪婪算法 贪婪算法分阶段地工作。在每个阶段&#xff0c;可以认为所做决定是最好的&#xff0c;而不考虑将来的后果。通常这意味着选择的是某个局部最优。这种“当前能获得的最优就拿”的策略是这类算法的名字来源。当算法终止时候&#xff0c;我们希望的到累积的局部最优解就…

[C++STL]C++ 实现map容器和set容器

代码如下: #pragma once #include <iostream> using namespace std;enum COLOR {BLACK, RED };template<class V>//迭代器声明&#xff0c;定义在后面 struct RBTreeIterator;template<typename V> struct RBTreeNode {RBTreeNode<V> * _parent;RBTre…

多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用

如果大家读过dapper源码&#xff0c;你会发现这内部有很多方法都用到了yield关键词&#xff0c;那yield到底是用来干嘛的&#xff0c;能不能拿掉&#xff0c;拿掉与不拿掉有多大的差别&#xff0c;首先上一段dapper中精简后的Query方法&#xff0c;先让大家眼见为实。private s…

C++泛型编程实现哈希表(闭散列---线性探测)

代码如下: #include <iostream> #include <vector> using namespace std;enum STATE {EXIST,DELETE,EMPTY };template<typename K,typename V> struct HashNode {pair<K, V> _kv;STATE _state EMPTY; };template<typename K,typename V> class…

哪种开源许可证最适合商业化?

选择最佳开源许可证是为新项目所做的最重要的决定之一。大多数开发者会选用 MIT、BSD 或 Apache 等流行的宽松许可证&#xff08;permissive license&#xff09;。对于商业项目而言&#xff0c;这种选择不错&#xff0c;因为这能减少用户对项目的抵触情绪。当应用于开源项目时…

C++泛型编程实现哈希表(开散列法)

代码如下: #include <iostream> #include <vector> using namespace std;template<typename K> struct HashNode {typedef HashNode<K> Node;K _val;Node * _next;HashNode(const K & val):_val(val),_next(nullptr){} };template<typename K&…

数据结构与算法--分治算法-最大子序列和问题

分治算法 用于设计算法的一种常用技巧–分治算法&#xff08;divide and conquer&#xff09;。分治算法由两部分组成&#xff1a; 分(divide)&#xff1a;递归然后借机较小的问题&#xff08;基础情况除外&#xff09;治(conquer)&#xff1a;然后从子问题的解构建原问题的解…