zoukankan      html  css  js  c++  java
  • 职责链模式(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  还是个新站,在持续关注中

  • 相关阅读:
    转载+自己心得
    分享
    领域驱动设计系列文章汇总
    ABP集合贴
    MVC学习系列——参考
    MVC学习系列——RazorViewEngine扩展
    MVC学习系列——Model验证扩展
    MVC学习系列——HtmlHelper扩展
    MVC学习系列——ModelBinder扩展
    MacBook强制清除gardle缓存
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6400478.html
Copyright © 2011-2022 走看看