zoukankan      html  css  js  c++  java
  • 设计模式之责任链

    责任链模式介绍

    通过链条连接

    责任链模式是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

    责任链模式的核心是解决一组服务中的先后执行处理关系。

    责任链模式可以让各个服务模块更加清晰,而每一个模块可以通过next的方式进行获取。而每一个next是由继承的统一抽象类实现的,最终所有类的职责可以动态的进行编排使用,编排的过程可以做成可配置化。

    在使用责任链时,如果场景比较固定,可写死到代码中进行初始化。但如果业务场景经常变化可以做成xml配置的方式进行处理,也可以保存到数据库中进行初始化操作。

    实际的业务中在使用责任链时会进行一系列的包装,通过把不同的责任节点进行组装,构成一条完整业务的责任链。

    责任链模式很好的处理单一职责和开闭原则,简单耦合也使对象关系更加清晰,而且外部的调用方并不需要关系责任链是如何处理的。

    责任链模式结构

    • 处理者
      声明了所有具体处理者的通用接口,该接口通常仅包含单个方法用于请求处理,但有时其还会包含一个设置链上下处理者的方法。
    • 基础处理者
      是一个可选的类,你可以将所有处理者共用的样本代码放置在其中。(通常情况下,该类定义了一个保存对于下个处理者引用的成员变量。客户端可通过将处理者的构造函数或设定方法来创建链。该类还可以实现默认的处理行为,确定下个处理者存在后再将请求传递给它。)
    • 具体处理者
      包含处理请求的实际代码。每个处理者接收到请求后,都必须决定是否进行处理,或者说是否沿着链传递请求。
    • 客户端
      可根据程序逻辑一次性或者动态的生成链。

    适用场景

    • 当程序需要使用不同方式处理不同种类请求,而且请求类型和顺序预先未知时。
    • 业务逻辑必须按顺序执行多个处理者时。
    • 处理者及其顺序必须在运行时进行改变,可以使用责任链模式。

    实现方式

    • 声明处理者接口并描述请求处理方法的签名
    • 可以根据处理者接口创建抽象处理者基类(需要一个成员变量来存储指向链上下个处理者的引用)
    • 创建具体的处理者子类并实现其处理方法。(每个处理者在接收到请求后都必须做两个决定:1、是否自行处理请求;2、是否将该请求沿着链进行传递。)
    • 客户端可自行组装链,或者从其他对象处获得预先组装好的链。
    • 客户端可触发链中的任意处理者,而不仅仅是第一个。请求将通过链进行传递,直至某个处理者拒绝继续传递或者请求到达链尾。

    Demo

    责任链模式在C#程序中并不常见,因为它仅在代码与对象链打交道时才能发货作用。

    处理者接口

        /// <summary>
        /// 处理者接口
        /// </summary>
        public interface IHandler 
        {
            IHandler SetNext(IHandler handler);
            object Handle(object request);
        }
    

    抽象类

        /// <summary>
        /// 抽象类
        /// </summary>
        public abstract class AbstractHandler :IHandler
        {
    
            private IHandler _nextHandler;
    
            public IHandler SetNext(IHandler handler)
            {
                this._nextHandler = handler;
                return handler;
            }
    
            /// <summary>
            /// 虚方法,在子类继承中需实现此方法。
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            public virtual  object Handle(object request)
            {
                if (this._nextHandler !=null)
                {
                    return this._nextHandler.Handle(request);
                }
                else
                {
                    return null;
                }
            }
        }
    

    实现抽象类

        /// <summary>
        /// 猴子类
        /// </summary>
        public class MonkeyHandler : AbstractHandler
        {
            public override object Handle(object request)
            {
                if ((request as string)=="猴子")
                {
                    return "在猴子类中"+request.ToString();
                }
                else
                {
                    return base.Handle(request);                        //父类中的Handle方法        
                }
            }
        }
    
        /// <summary>
        /// 松鼠类
        /// </summary>
        public class SquirreHandler : AbstractHandler
        {
            public override object Handle(object request)
            {
                if ((request as string) == "松鼠")
                {
                    return "在松鼠类中" + request.ToString();
                }
                else
                {
                    return base.Handle(request);                        //父类中的Handle方法        
                }
            }
        }
    
        /// <summary>
        /// 小狗类
        /// </summary>
        public class DogHandler : AbstractHandler
        {
            public override object Handle(object request)
            {
                if ((request as string) == "小狗")
                {
                    return "在小狗类中" + request.ToString();
                }
                else
                {
                    return base.Handle(request);                        //父类中的Handle方法        
                }
            }
        }    
    

    客户端和Main()验证

        class Client 
        {
            public static void ClientCode(AbstractHandler handler) 
            {
                foreach (var item in new List<string>{"松鼠","猴子","人"})
                {
                    Console.WriteLine("到底是谁:"+item);
                    var result = handler.Handle(item);
                    if (result!=null)
                    {
                        Console.WriteLine("谁:"+result);
                    }
                    else
                    {
                        Console.WriteLine("No Find");
                    }
                }
                Console.WriteLine("开始");
            }
        
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var monkey = new MonkeyHandler();
                var squirrel = new SquirreHandler();
                var dog = new DogHandler();
    
                monkey.SetNext(squirrel).SetNext(dog);      //构建链条
    
                Console.WriteLine("----------第一次");
                Client.ClientCode(monkey);
                Console.WriteLine();
                Console.WriteLine("第二次");
                Client.ClientCode(squirrel);
                Console.WriteLine("第三次");
                Client.ClientCode(dog);
                Console.ReadKey();
            }
        }
    

    输出结果

    可以通过上面图片标红的地方了解到具体输出的值,第一次(初始位置)时在最后狗类处不继续执行,第二次(中间位置)在猴子类处不执行,第三次所有的都不执行(第三次到链尾了)。

    小寄语

    人生短暂,我不想去追求自己看不见的,我只想抓住我能看的见的。

    我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发 谢谢。

    作者:阿辉
    关注我:微信扫描下面二维码,6T编程资料免费送。
    微信公众号:Andy阿辉
    写一些程序员的所思所想,希望对你有帮助。

    版权声明:本文版权归作者和博客园共有,欢迎转载,
    但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    Java 常见异常种类
    Oracle存储过程记录异常
    oracle定时器
    oracle生成单据号
    oracle计算时间秒数差
    oracle分组后取每组第一条数据
    was部分更新
    数据库分区
    JTA事务管理
    docker
  • 原文地址:https://www.cnblogs.com/netxiaohui/p/15173987.html
Copyright © 2011-2022 走看看