从真实项目中抠出来的设计模式——第三篇:责任链模式
一:现实场景
有时候在开发的过程中,我们经常会根据某个状态的值,写出很多的ifelse逻辑,比如拿项目里面的案例来说,如果当前发送的是彩信,此种状态需要如何给
实体赋值,如果是短信,邮件又是其他方式的赋值,等等此类,这种情况下一般会写出如下if判断,对吧,真实代码如下:
1 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.邮件)) 2 { 3 //第三步:动态生成邮件模板 4 var styleInfo = CacheUtil.GetRandomEmailStyle(); 5 6 var tuple = new EdmDraftBoxBLL().GetEdmHtmlTitle(communicationInfo.EDMJson, styleInfo.StyleId); 7 8 leaflet.Title = tuple.Item1; 9 leaflet.EDMContent = tuple.Item2; 10 leaflet.Header = tuple.Item3; 11 leaflet.SendSMSCount = 1; 12 } 13 14 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.短信)) 15 { 16 leaflet.SMSContent = communicationInfo.SMSContent; 17 leaflet.SendSMSCount = communicationInfo.SMSCount; 18 } 19 20 21 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信)) 22 { 23 leaflet.MMSContent = communicationInfo.MMSContent; 24 }
上面的代码还是非常简单明了的,程序会根据leaflet.CommunicationtypeEnum的不同做不同的判断,比如说当前状态是邮件的话,程序会从30套邮件
模板库中随机抽取一封,给leaflet的title,header...赋值,有些人可能会说这段代码不难看哈,确实是这样,但是如果面对需求变更呢?比如说后期需要增加微
信,微博渠道,那是不是又要加上两个if才能把这个问题解决呢? 这就违背了设计模式中开闭原则,对吧,面对这种场景,可以用责任链模式摆平。
二:责任链模式
责任链模式讲的就是将请求的发送者和接收者进行分离,避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,
并且沿着这条链传递请求,直到有对象处理它为止,面对需求变更,只需要更加处理类就好了,而且客户端可以按照自己的需求拼接处理链条,是不是很强大。
1. AbstractComunication
public abstract class AbstractComunication { AbstractComunication abstractComunication = null; public void SetHandler(AbstractComunication abstractComunication) { this.abstractComunication = abstractComunication; } public abstract void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo); }
2. MMSComunication
1 public class MMSComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信)) 6 { 7 leaflet.MMSContent = communicationInfo.MMSContent; 8 } 9 else 10 { 11 abstractComunication.HanderRequest(leaflet, communicationInfo); 12 } 13 } 14 }
3.EDMComunication
1 public class EDMComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.邮件)) 6 { 7 //第三步:动态生成邮件模板 8 var styleInfo = CacheUtil.GetRandomEmailStyle(); 9 10 var tuple = new EdmDraftBoxBLL().GetEdmHtmlTitle(communicationInfo.EDMJson, styleInfo.StyleId); 11 12 leaflet.Title = tuple.Item1; 13 leaflet.EDMContent = tuple.Item2; 14 leaflet.Header = tuple.Item3; 15 leaflet.SendSMSCount = 1; 16 } 17 else 18 { 19 abstractComunication.HanderRequest(leaflet, communicationInfo); 20 } 21 } 22 }
4.SMSComunication
1 public class SMSComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.短信)) 6 { 7 leaflet.SMSContent = communicationInfo.SMSContent; 8 leaflet.SendSMSCount = communicationInfo.SMSCount; 9 } 10 else 11 { 12 abstractComunication.HanderRequest(leaflet, communicationInfo); 13 } 14 } 15 }
5.客户端调用
1 AbstractComunication communication1 = new EDMComunication(); 2 AbstractComunication communication2 = new SMSComunication(); 3 AbstractComunication communication3 = new MMSComunication(); 4 5 //手工将三个Comunication 凭借成一个链条,形成单链表的模型 6 communication1.SetHandler(communication2); 7 communication2.SetHandler(communication3); 8 9 communication1.HanderRequest(leaflet, communicationInfo);
其实上面的代码,需要绕一下脑子的就是如何通过SetHandler将三个xxxComunication拼接成一个单链表的形式,链表怎么拼接在于客户端如何设置sethandler,
灵活性完全就在客户端这边,然后就非常方便将leaflet在责任链中游走,最终会被某一状态处理逻辑处理,讲到这里,我想大家应该都知道责任链模式是干嘛的了,
由于是真实案例就不方便跑代码了,下面我构建一个责任链模型,大家比照一下就可以了,是不是有种请求和处理的分离,而且我还可以根据需要组合我的责任链,
其实js的冒泡机制就是这种模式的一个体现。
public abstract class AbstractHandler { protected AbstractHandler abstractHandler = null; public void SetHandler(AbstractHandler abstractHandler) { this.abstractHandler = abstractHandler; } public virtual void HandleRequest(int request) { } } public class ConcreteHandler1 : AbstractHandler { public override void HandleRequest(int request) { if (request == 1) { Console.WriteLine("handler1 给你处理了"); } else { abstractHandler.HandleRequest(request); } } } public class ConcreteHandler2 : AbstractHandler { public override void HandleRequest(int request) { if (request == 2) { Console.WriteLine("handler2 给你处理了"); } else { abstractHandler.HandleRequest(request); } } } public class ConcreteHandler3 : AbstractHandler { public override void HandleRequest(int request) { if (request == 3) { Console.WriteLine("handler3 给你处理了"); } else { abstractHandler.HandleRequest(request); } } } class Program { static void Main(string[] args) { AbstractHandler hander1 = new ConcreteHandler1(); AbstractHandler hander2 = new ConcreteHandler2(); AbstractHandler hander3 = new ConcreteHandler3(); hander1.SetHandler(hander2); hander2.SetHandler(hander3); hander1.HandleRequest(3); } }
好了,模板和实际项目的案例都给大家展示了,希望能帮助到你。
相关文章
- 记一次 .NET 某自动化采集软件 崩溃分析
- [C# 中的序列化与反序列化](.NET 源码学习)
- .NET 向量类型的运算结果范例——用于学习Vector类所提供百多个向量方法
- 树莓派(香橙派)通过.NET IoT 操作SPI编写屏幕驱动 顺手做个四足机器人(一)
- WPF自定义控件之消息提示
- .NET跨平台框架选择之一 - Avalonia UI
- 篇(16)-Asp.Net Core入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证二)
- 学习ASP.NET Core Blazor编程系列十——路由(下)
- 代码生成器(CodeBuilder) 2.9.4 稳定版
- 篇(15)-入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证一)
- 篇(14)-Asp.Net Core入门实战-权限管理之角色编辑和赋权(ViewModel-DTO初探)
- 算法-2 选择排序、冒泡排序、插入排序
- 篇(13)-Asp.Net Core入门实战-将功能代码增加异步功能Async和配置简单防范CSRF攻击
- NET 6 实现滑动验证码(一)、创建工程
- 算法-1 算法复杂度
- 在WPF中使用Prism弹出自定义窗体样式的对话框
- 使用Fody时,CS-SCRIPT动态代码无法找到程序集
- C# 使用SIMD向量类型加速浮点数组求和运算(3):循环展开
- aspnetcore两种上传图片(文件)的方式
- WPF输入验证提示