职责链模式

来源:互联网 发布:linux 启动openoffice 编辑:程序博客网 时间:2024/05/17 01:58

职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

该模式UML结构图:

这里写图片描述

基本代码:

    public abstract class Handler    {        protected Handler successor;        //设置继任者        public void SetSuccessor(Handler successor)         {            this.successor = successor;        }        //处理请求的抽象方法        public abstract void HandleRequest(int request);    }    public class ConcreteHandler1 : Handler     {        public override void HandleRequest(int request)        {            if (request >= 0 && request < 10)            {                Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);            }            else if(request!=null)            {                successor.HandleRequest(request);            //转移下一位            }        }    }    public class ConcreteHanlder2 : Handler     {        public override void HandleRequest(int request)        {            if (request >= 10 && request < 20)            {                Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);            }            else if (request != null)            {                successor.HandleRequest(request);          //转移下一位            }        }    }    public class ConcreteHandler3 : Handler     {        public override void HandleRequest(int request)        {            if (request >= 20 && request < 30)            {                Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);            }            else if (request != null)            {                successor.HandleRequest(request);          //转移下一位            }        }    }

客户端调用:

            Handler h1 = new ConcreteHandler1();            Handler h2 = new ConcreteHanlder2();            Handler h3 = new ConcreteHandler3();            h1.SetSuccessor(h2);            h2.SetSuccessor(h3);                   //设置上下链的关系            int[] requests = new int[] {2,5,14,22,18,3,27,20 };            foreach (var item in requests)            {                h1.HandleRequest(item);            }            Console.ReadLine();

结果:
这里写图片描述

下面请听题:
=小菜在单位,向领导请假,小于等于2天经理有权利批准,小于等于5天总监有权利批准,其他的则要交到总经理那里批准。

代码:

    //申请类    public class Request    {        //申请类型   比如加薪 请假        public  string RequestType { get; set; }        //申请内容        public  string RequestContent { get; set; }        //天数  或钱的数量        public int Number { get; set; }    }   //管理者类    public abstract class Manager    {        protected string name;        public Manager(string name)        {            this.name = name;        }        protected Manager manager;        public void SetManager(Manager manager)        {            this.manager = manager;        }        //申请请求        public abstract void RequestApplication(Request request);    }    //经理类    public class CommonManager : Manager    {        public CommonManager(string name) : base(name) { }        public override void RequestApplication(Request request)        {            if (request.RequestType == "请假" && request.Number <= 2)            {                Console.WriteLine("{0}:{1}数量{2}  被批准", name, request.RequestContent, request.Number);            }            else if (manager !=null)            {                manager.RequestApplication(request);            }        }    }    //总监类    public class Majordomo : Manager     {        public Majordomo(string name) : base(name) { }        public override void RequestApplication(Request request)        {            if (request.RequestType == "请假" && request.Number <= 5)            {                Console.WriteLine("{0}:{1}数量{2}  被批准", name, request.RequestContent, request.Number);            }            else if(manager!=null)            {                manager.RequestApplication(request);            }        }     }    //总经理类    public class GeneralManager : Manager     {        public GeneralManager(string name) : base(name) { }        public override void RequestApplication(Request request)        {            if (request.RequestType == "请假")            {                Console.WriteLine("{0}:{1}数量{2}  被批准", name, request.RequestContent, request.Number);            }            else if (request.RequestType == "加薪" && request.Number <= 500)            {                Console.WriteLine("{0}:{1}数量{2}  被批准", name, request.RequestContent, request.Number);            }            else if (request.RequestType == "加薪" && request.Number > 500)            {                Console.WriteLine("{0}:{1}数量{2}  再说吧", name, request.RequestContent, request.Number);            }        }    }

客户端调用:

    CommonManager jingli = new CommonManager("经理");            Majordomo zongjian = new Majordomo("总监");            GeneralManager zongjingli = new GeneralManager("总经理");            //设置上下级关系   经理->总监->总经理            jingli.SetManager(zongjian);            zongjian.SetManager(zongjingli);            Request request = new Request();            request.RequestType = "请假";            request.RequestContent = "小菜要请假";            request.Number = 2;            jingli.RequestApplication(request);            Request request2 = new Request();            request2.RequestType = "请假";            request2.RequestContent = "小菜要请假";            request2.Number = 5;            jingli.RequestApplication(request2);            Request request3 = new Request();            request3.RequestType = "加薪";            request3.RequestContent = "小菜要加薪";            request3.Number = 500;            jingli.RequestApplication(request3);            Request request4 = new Request();            request4.RequestType = "加薪";            request4.RequestContent = "小菜要加薪";            request4.Number = 1000;            jingli.RequestApplication(request4);

结果:
这里写图片描述

职责链模式的好处:
当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。
这样做的好处是,请求者不用管那个对象来处理,反正该请求会被处理就对了。
接收着和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个指向其后继者的引用,而不需要保持他所选接收者的引用。 这就大大的降低了耦合度。

四、优缺点及适用场景

优点:

1)降低了请求发送者和处理者之间的耦合。

2)把多个条件判定分散到各个处理类中,使得代码更加清晰,责任更加明确。

缺点:

1)在找到正确的处理对象之前,所有的条件判定都要执行一遍,当职责链过长时,可能会引起性能问题。

2)可能导致某个请求不被处理。

适用场景:

1)一个系统的请求需要多个对象进行审批才能完成的情况。

2)代码中有多个if-else时,也可以考虑使用职责链模式对代码进行重构。

0 0