职责链模式(23)

来源:互联网 发布:撤销中国根域名服务器 编辑:程序博客网 时间:2024/06/05 05:18

今天我们来讲一下职责链模式。首先我们来模拟一下下面这个场景。

一、案例

在公司,我们需要向领导请假,向领导申请加薪,不同级别的领导会做出相应的批示。下面我们用简单的控制台应用程序来模拟一下这个案例。

  1     /// <summary>  2     /// 申请类  3     /// </summary>  4     class Request  5     {  6         //申请类别  7         private string requestType;  8         public string RequestType  9         { 10             get 11             { 12                 return requestType; 13             } 14  15             set 16             { 17                 requestType = value; 18             } 19         } 20         //申请内容 21         private string requestContent; 22         public string RequestContent 23         { 24             get 25             { 26                 return requestContent; 27             } 28  29             set 30             { 31                 requestContent = value; 32             } 33         } 34         //数量 35         private int number; 36         public int Number 37         { 38             get 39             { 40                 return number; 41             } 42  43             set 44             { 45                 number = value; 46             } 47         } 48     } 49  50     /// <summary> 51     /// 管理者类 52     /// </summary> 53     class Manager 54     { 55         protected string name; 56  57         public Manager(string name) 58         { 59             this.name = name; 60         } 61         //得到结果 62         public void GetResult(string managerLevel, Request request) 63         { 64             //比较长的方法,多条的分支,这些其实都是代码坏味道 65             if (managerLevel == "经理") 66             { 67                 if (request.RequestType == "请假" && request.Number <= 2) 68                 { 69                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 被批准"); 70                 } 71                 else 72                 { 73                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 我无权处理"); 74                 } 75             } 76             else if (managerLevel == "总监") 77             { 78                 if (request.RequestType == "请假" && request.Number <= 5) 79                 { 80                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 被批准"); 81                 } 82                 else 83                 { 84                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 我无权处理"); 85                 } 86             } 87             else if (managerLevel=="总经理") 88             { 89                 if (request.RequestType=="请假") 90                 { 91                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 被批准"); 92                 } 93                 else if (request.RequestType=="加薪"&&request.Number<=500) 94                 { 95                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 被批准"); 96                 } 97                 else if (request.RequestType == "加薪" && request.Number > 500) 98                 { 99                     Console.WriteLine($"{name}:{request.RequestContent} 数量{request.Number} 再说吧");100                 }101             }102         }103     }

客户端调用:

 1         public static void Main() 2         { 3             //三个管理者 4             Manager jinli = new Manager("金立"); 5             Manager zongjian = new Manager("宗剑"); 6             Manager zhongjingli = new Manager("钟精励"); 7  8             //小魔王请求加薪1000 9             Request request = new Request();10             request.RequestType = "加薪";11             request.RequestContent = "小魔王请求加薪";12             request.Number = 1000;13 14             //不同级别对此请求做判断和处理15             jinli.GetResult("经理", request);16             zongjian.GetResult("总监", request);17             zhongjingli.GetResult("总经理", request);18 19             //请假3天20             Request request2 = new Request();21             request2.RequestType = "请假";22             request2.RequestContent = "小魔王请假";23             request2.Number = 3;24 25             // 不同级别对此请求做判断和处理26             jinli.GetResult("经理", request2);27             zongjian.GetResult("总监", request2);28             zhongjingli.GetResult("总经理", request2);29 30             Console.ReadKey();31         }

好,下面我们来分析一下上述代码,看看有什么问题和缺陷。

①:GetResult这个方法太长,分支太多,让人感觉很不舒服,代码坏了味道。违背了单一职责的原则

②:如果还有其他的管理级别的管理者,那么,就需要修改Manager类,违背了开放-封闭原则。

我们如何才能不仅实现功能,而且还能解决上述的问题呢?下面就是我们要讲的职责链模式了。

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

我们来看一下它的代码结构

 1     //定义一个处理请示的接口 2     abstract class Handler 3     { 4         protected Handler successor; 5         //设置继任者 6         public void SetSuccessor(Handler successor) 7         { 8             this.successor = successor; 9         }10         //处理请求的抽象方法11         public abstract void HandleRequest(int request);12     }13 14     //具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理请求就处理它,15     //否则,将该请求转发给它的后继者。16     class ConcreteHandler1 : Handler17     {18         public override void HandleRequest(int request)19         {20             if (request >= 0 && request < 10)21             {22                 Console.WriteLine($"{this.GetType().Name}{request}");23             }24             else if (successor != null)25             {26                 //转移到下一位去处理27                 successor.HandleRequest(request);28             }29         }30     }31     class ConcreteHandler2 : Handler32     {33         public override void HandleRequest(int request)34         {35             if (request >= 10)36             {37                 Console.WriteLine($"{this.GetType().Name}{request}");38             }39             else if (successor != null)40             {41                 //转移到下一位去处理42                 successor.HandleRequest(request);43             }44         }45     }

客户端

 1         public static void Main() 2         { 3             Handler h1 = new ConcreteHandler1(); 4             Handler h2 = new ConcreteHandler2(); 5             h1.SetSuccessor(h2); 6  7             int[] requests = {2, 5, 14, 22}; 8             foreach (int request in requests) 9             {10                 h1.HandleRequest(request);11             }12             Console.ReadKey();13         }

这当中,最关键的是当客户提交一个请求时,请求是沿着链传递直至有一个ConcreteHandler对象负责处理它。接收者和发送者都没有对方的明确消息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,他们仅需保持一个指向其后继者的引用,而不需要保持它所有的候选接受着的引用。

下面,我们用职责链模式将我们案例重构一下。

  1     /// <summary>  2     /// 申请类  3     /// </summary>  4     class Request  5     {  6         //申请类别  7         private string requestType;  8         public string RequestType  9         { 10             get 11             { 12                 return requestType; 13             } 14  15             set 16             { 17                 requestType = value; 18             } 19         } 20         //申请内容 21         private string requestContent; 22         public string RequestContent 23         { 24             get 25             { 26                 return requestContent; 27             } 28  29             set 30             { 31                 requestContent = value; 32             } 33         } 34         //数量 35         private int number; 36         public int Number 37         { 38             get 39             { 40                 return number; 41             } 42  43             set 44             { 45                 number = value; 46             } 47         } 48     }    49     //管理者 50     abstract class Manager 51     { 52         protected string name; 53         //管理者的上级 54         protected Manager superior; 55  56         public Manager(string name) 57         { 58             this.name = name; 59         } 60         //设置管理者的上级 61         public void SetSuperior(Manager superior) 62         { 63             this.superior = superior; 64         } 65  66         abstract public void RequestApplications(Request request); 67     } 68     //经理 69     class CommonManager:Manager 70     { 71         public CommonManager(string name) : base(name) 72         { 73         } 74  75         public override void RequestApplications(Request request) 76         { 77             if (request.RequestType == "请假" && request.Number <= 2) 78             { 79                 Console.WriteLine($"{name}{request.RequestContent}{request.Number}"); 80             } 81             else 82             { 83                 //其余的申请都需转到上级 84                 if (superior!=null) 85                 { 86                     superior.RequestApplications(request); 87                 } 88             } 89         } 90     } 91     //总监 92     class Majordomo : Manager 93     { 94         public Majordomo(string name) : base(name) 95         { 96         } 97  98         public override void RequestApplications(Request request) 99         {100             if (request.RequestType == "请假" && request.Number <= 5)101             {102                 Console.WriteLine($"{name}{request.RequestContent}{request.Number}");103             }104             else105             {106                 //其余的申请都需转到上级107                 if (superior != null)108                 {109                     superior.RequestApplications(request);110                 }111             }112         }113     }114     //总经理115     class GeneralManager : Manager116     {117         public GeneralManager(string name) : base(name)118         {119         }120 121         public override void RequestApplications(Request request)122         {123             if (request.RequestType == "请假" )124             {125                 Console.WriteLine($"{name}{request.RequestContent}{request.Number}");126             }127             else if (request.RequestType=="加薪"&&request.Number<=500)128             {129                 Console.WriteLine("批准");130             }131             else132             {133                 Console.WriteLine("再说吧");134             }135         }136     }

客户端:

 1         public static void Main() 2         { 3             CommonManager jinli = new CommonManager("金立"); 4             Majordomo zongjian = new Majordomo("宗剑"); 5             GeneralManager zhongjingli = new GeneralManager("钟精励"); 6             //根据实际需求设置上级 7             jinli.SetSuperior(zongjian); 8             zongjian.SetSuperior(zhongjingli); 9 10             //客户端的申请都是由‘经理’发起,但实际上谁来决策由具体的管理类来处理,客户端不知道。11             Request request = new Request();12             request.RequestType = "请假";13             request.RequestContent = "小魔王请假";14             request.Number = 1;15             jinli.RequestApplications(request);16 17             Request request2 = new Request();18             request2.RequestType = "请假";19             request2.RequestContent = "小魔王请假";20             request2.Number = 4;21             jinli.RequestApplications(request2);22 23             Request request3 = new Request();24             request2.RequestType = "加薪";25             request2.RequestContent = "小魔王加薪";26             request2.Number = 1000;27             jinli.RequestApplications(request2);28 29             Console.ReadKey();30         }

好了,职责链模式就讲到这里了,下一篇我们讲 中介者模式


 本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持

0 0
原创粉丝点击