19.Chain of Responsibility职责链(行为型模式)

一:动机(Motivation)

在这里插入图片描述

<1>在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显式指定,将必不可少地带来请求发送者与接受者的紧耦合。
<2>如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。

二:意图(Intent)

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
——《设计模式》GoF

三:结构(Structure)

在这里插入图片描述

在这里插入图片描述

四:结构详解

在这里插入图片描述

五:生活中的例子

员工向主管上级提出申请

申请有两种:请假和加薪
职责链是:总监>经理>总经理
总监能处理:请假,且在2小时以内
经理能处理:请假,且在5小时以内
总经理能处理:
请假:小时不限,都通过
加薪:
1000元以内批准
1000元以上要考察再说

在这里插入图片描述

六:实现

namespace Test
{
    public enum 申请类型
    {
        请假,
        加薪
    }

    /// <summary>
    /// 实现申请
    /// </summary>
    public class 申请
    {
        public 申请类型 类型;
        public string 内容;
        public int 数量;
        public override string ToString()
        {
            return string.Format("内容:{0},类型:{1},数量:{2}", this.内容, this.类型, this.数量);
        }
    }

    /// <summary>
    /// 实现管理者
    /// </summary>
    public abstract class 管理者
    {
        protected string name;
        public 管理者(string 姓名)
        {
            this.name = 姓名;
        }

        protected 管理者 superior;
        public 管理者 上级主管
        {
            get { return this.superior; }
            set { this.superior = value; }
        }

        public abstract void 处理员工申请(申请 request);
    }

    /// <summary>
    /// 实现总监
    /// </summary>
    public class 总监 : 管理者
    {
        public 总监(string 姓名) : base(姓名) { }

        public override void 处理员工申请(申请 request)
        {
            if (request.类型 == 申请类型.请假 && request.数量 <= 2)
            {
                Console.WriteLine("总监:{0},通过 {1} 申请,数量:{2}", base.name, request.内容, request.数量);
            }
            else
            {
                if (base.superior != null)
                {
                    Console.WriteLine("总监:{0},无权处理 {1} 申请,数量:{2},转交给上级", base.name, request.内容, request.数量);
                    base.superior.处理员工申请(request);
                }
            }
        }
    }

    /// <summary>
    /// 实现经理
    /// </summary>
    public class 经理 : 管理者
    {
        public 经理(string 姓名) : base(姓名) { }

        public override void 处理员工申请(申请 request)
        {
            if (request.类型 == 申请类型.请假 && request.数量 <= 5)
            {
                Console.WriteLine("经理:{0},通过 {1} 申请,数量:{2}", base.name, request.内容, request.数量);
            }
            else
            {
                if (base.superior != null)
                {
                    Console.WriteLine("经理:{0},无权处理 {1} 申请,数量:{2},转交给上级", base.name, request.内容, request.数量);
                    base.superior.处理员工申请(request);
                }
            }
        }
    }

    /// <summary>
    /// 实现总经理
    /// </summary>
    public class 总经理 : 管理者
    {
        public 总经理(string 姓名) : base(姓名) { }

        public override void 处理员工申请(申请 request)
        {
            if (request.类型 == 申请类型.请假)
            {
                Console.WriteLine("总经理:{0},通过 {1} 申请,数量:{2}", base.name, request.内容, request.数量);
                return;
            }
            else
            {
                if (request.类型 == 申请类型.加薪 && request.数量 <= 1000)
                {
                    Console.WriteLine("总经理:{0},无权处理 {1} 申请,数量:{2}", base.name, request.内容, request.数量);
                    return;
                }
                else
                {
                    Console.WriteLine("总经理:{0},没有通过 {1} 申请,数量:{2},再考察一下工作表现再说吧", base.name, request.内容, request.数量);
                    return;
                }
            }
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            申请 request = new 申请();
            request.类型 = 申请类型.请假;
            request.数量 = 1;
            request.内容 = "小李要请假";

            管理者 张三 = new 总监("张三");
            管理者 李四 = new 经理("李四");
            管理者 王五 = new 总经理("王五");
            张三.上级主管 = 李四;
            李四.上级主管 = 王五;

            Console.WriteLine("\n第1次申请:{0}", request);
            张三.处理员工申请(request);
            request.数量 = 8;
            Console.WriteLine("\n第2次申请:{0}", request);
            张三.处理员工申请(request);

            request.类型 = 申请类型.加薪;
            request.内容 = "小李要涨工资";
            request.数量 = 800;
            Console.WriteLine("\n第3次申请:{0}", request);
            张三.处理员工申请(request);

            request.数量 = 1500;
            Console.WriteLine("\n第4次申请:{0}", request);
            张三.处理员工申请(request);
            Console.ReadLine();
        }
    }
}

实现-结果

在这里插入图片描述

七:实现要点

<1>链的顺序可灵活改变-改变”上级主管”即可;
<2>发起请求者只需要将请求发送给”最近”的上级,即总监,不需要关心后续的链接关系。

八:适用性

<1>系统已经有一个由处理者对象组成的链。这个链可能由复合模式给出;
<2>当有多于一个的处理者对象会处理一个请求,而且在事先并不知道到底由哪一个处理者对象处理一个请求。这个处理者对象是动态确定的;
<3>当系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理此请求;
<4>当处理一个请求的处理者对象集合需要动态地指定时。

九:总结

<1>Chain of Responsibility 模式的应用场合在于“一个请求可能有多个接受者,但是最后真正的接受者只有一个”,只有这时候请求发送者与接受者的耦合才有可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好地应对变化。
<2>应用了Chain of Responsibility 模式后,对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理职责。
<3>如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受对象的责任,而不是发出请求的对象的责任。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值