热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从真实项目中抠出来的设计模式——第三篇:责任链模式

一:现实场景有时候在开发的过程中,我们经常会根据某个状态的值,写出很多的ifelse逻辑,比如拿项目里面的案例来说,如果当前发送的是彩信,此种状态需要如何给实体赋值,如果是短信,邮件又是其他方

一:现实场景

    有时候在开发的过程中,我们经常会根据某个状态的值,写出很多的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);
}
}

 

好了,模板和实际项目的案例都给大家展示了,希望能帮助到你。

 


推荐阅读
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 在编写业务代码时,常常会遇到复杂的业务逻辑导致代码冗长混乱的情况。为了解决这个问题,可以利用中间件模式来简化代码逻辑。中间件模式可以帮助我们更好地设计架构和代码,提高代码质量。本文介绍了中间件模式的基本概念和用法。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
author-avatar
A布匹rray
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有