职责链模式(23)

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

一、案例

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

  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 : Handler
17     {
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 : Handler
32     {
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             else
105             {
106                 //其余的申请都需转到上级
107                 if (superior != null)
108                 {
109                     superior.RequestApplications(request);
110                 }
111             }
112         }
113     }
114     //总经理
115     class GeneralManager : Manager
116     {
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             else
132             {
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         }

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


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

推荐一个.net界的网站:OurDotNet  还是个新站,在持续关注中

posted @ 2017-02-15 10:54  萌萌丶小魔王  阅读(261)  评论(0编辑  收藏  举报