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

动机(Motivation)

在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合。

如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而让两者解耦。

意图(Intent)

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

结构(Structure)

其中,

Handler:定义一个处理请示的接口

ConcerteHandler1:具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继者

代码实现

实例背景:在公司,请假和加薪都要有各级审批制度,审批权限如下。(假设只涉及3个管理者:经理,总监和总经理)

申请请假:2天以内,经理审批。5天以内,总监有权审批。总经理可审批任何天数。

申请加薪:经理和总监无权。加薪500以内总经理批准,500-1000,总经理还需要在考虑是否加薪。

把处理员工申请的流程可以看做一个职责链,无论是请假还是加薪,都先由经理进行判断,经理若有权处理,则处理之,无权处理转交给他的上级(继任者),也就是总监。总监再次判断自己是否有权处理,有权处理,无权转交其上级(继任者)-总经理处理。

申请类:有RequestType申请类别,RequestContent申请内容和Number申请数量这三个字段属性。

     class Request
    {
        //申请类别
        private string requestType;
        public string RequestType
        {
            get { return requestType; }
            set { requestType = value; }
        }
        //申请内容  同上...
        //数量      同上...

    }

管理者:对应于结构图中的Handler类,定义一个处理请示的接口,本实例中,定义了一个处理请假和审批的抽象方法RequestApplications(Request request)

    abstract class Manager
    {
        protected string name;
        //管理者的上级
        protected Manager superior;
        public Manager(string name)
        {
            this.name = name;
        }
        //设置管理者的上级
        public void SetSuperior(Manager superior)
        {
            this.superior = superior;
        }
        //申请请求
        abstract public void RequestApplications(Request request);
    }

经理类、总监类、总经理类:对应于结构图中的ConcreteHandler类,只需要重写“申请请求RequestApplications(Request request)”的方法就可以了

经理的权限是处理2天内的请假,其余申请转交给上级去处理

    //经理类
    class CommonManager : Manager
    {
        public CommonManager(string name):base(name) { }
        public override void RequestApplications(Request request)
        {
            if (request.RequestType=="请假" && request.Number<=2)
            {
                Console.WriteLine("{0}:{1}数量{2}被批准",name,request.RequestContent,request.Number);
            }
            else
            {
                if (superior != null)
                    superior.RequestApplications(request);
            }
        }
    }   

 总监类的代码和总经理类的代码与经理类代码类似,只是处理权限不同,总监所能有的权限就是可准许下属5天内的假期,其余申请都需要转到上级。总经理可以准许下属任意天的假期和判断是否可以加薪。

客户端代码

实例化出三个管理者:经理小王,总监小刘,总经理小张

 CommonManager jingli = new CommonManager("经理小王");
 Majordomo zongjian = new Majordomo("总监小刘");
 GeneralManager zongjingli = new GeneralManager("总经理小张");

设置上级:在这里,设置经理的上级是总监,总监的上级是总经理(可根据实际要求进行调整,较为灵活

jingli.SetSuperior(zongjian);
zongjian.SetSuperior(zongjingli);

第1个申请:申请类型:请假,申请内容:“小菜请假”,数量:1天

Request request1 = new Request();
request1.RequestType = "请假";
request1.RequestContent = "小菜请假";
request1.Number = 1;
jingli.RequestApplications(request1);

第2个申请: 申请类型:请假,申请内容:小菜请假,数量:4天

 Request request2 = new Request();
 request2.RequestType = "请假";
 request2.RequestContent = "小菜请假";
 request2.Number = 4;
 jingli.RequestApplications(request2);

可以看到客户端的申请都是由“经理”发起,但实际谁来决策由具体管理类来处理,客户端并不知道,加薪的请求也是一样,可参考上面请假代码

程序运行结果

Chian of Responsibility模式的几个要点

1.当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。

2.接受者和发送者都没有对方的明确消息,且链中的对象自己也并不知道链的结构,结果是职责链可以简化对象的相互连接,他们仅需保持一个指向其后继用者的引用,而不需要保持它所有的候选接受者的引用。

3.如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受对象的责任,而不是发出请求的对象的责任。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值