zoukankan      html  css  js  c++  java
  • 从真实项目中抠出来的设计模式——第三篇:责任链模式

    一:现实场景

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

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

  • 相关阅读:
    Markdown标签
    macbook使用
    git的使用
    HTTPS的原理
    javascript中的对象
    javascript中this的指向问题
    javascript中的闭包
    javaScript中的return、break和continue
    Promise对象
    ORACLE_11G归档空间满,由于数据库装完后使用的是默认空间是闪回区
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/6429284.html
Copyright © 2011-2022 走看看