• 23种设计模式之责任链模式(Chain of Responsibility Pattern)


    责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

    在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

    职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了

    优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

    缺点: 1、不能保证请求一定被接收。 2、在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题。 3、可能不容易观察运行时的特征,有碍于除错。

    应用实例: 1、JS 中的事件冒泡。2、在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在面试的完后,经常会有面试官说,你这个薪水我这边觉得你这技术可以拿这个薪水的,但是还需要技术总监的批准等的话。

    主要涉及两个角色

    • 抽象处理者角色(Handler):定义出一个处理请求的接口。这个接口通常由接口或抽象类来实现。
    • 具体处理者角色(ConcreteHandler):具体处理者接受到请求后,可以选择将该请求处理掉,或者将请求传给下一个处理者。因此,每个具体处理者需要保存下一个处理者的引用,以便把请求传递下去

    实现代码:

     1     public abstract class AbstractAuditor
     2     {
     3         public string Name { get; set; }
     4         public abstract void Audit(ApplyContext context);
     5 
     6         private AbstractAuditor _NextAuditor = null;
     7         public void SetNext(AbstractAuditor auditor)
     8         {
     9             this._NextAuditor = auditor;
    10         }
    11         protected void AuditNext(ApplyContext context)
    12         {
    13             if (this._NextAuditor != null)
    14             {
    15                 this._NextAuditor.Audit(context);
    16             }
    17             else
    18             {
    19                 context.AuditResult = false;
    20                 context.AuditRemark = "不允许请假!";
    21             }
    22         }
    23     }
    View Code
     1     /// <summary>
     2     /// 请假申请,
     3     /// Context--上下文环境,保存业务处理中参数-中间结果-最终结果
     4     /// 行为型设计模式常用的标配
     5     /// 把行为转移,
     6     /// </summary>
     7     public class ApplyContext
     8     {
     9         public int Id { get; set; }
    10         public string Name { get; set; }
    11         /// <summary>
    12         /// 请假时长
    13         /// </summary>
    14         public int Hour { get; set; }
    15         public string Description { get; set; }
    16         public bool AuditResult { get; set; }
    17         public string AuditRemark { get; set; }
    18     }
    View Code
     1     /// <summary>
     2     /// 职责问题:
     3     /// 1 权限范围内,审批通过
     4     /// 2 权限范围外,交给下一环节审批
     5     /// 写的代码又多了一个,指定下一环节
     6     /// 甩锅大法
     7     /// </summary>
     8     public class PM : AbstractAuditor
     9     {
    10         public override void Audit(ApplyContext context)
    11         {
    12             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
    13             if (context.Hour <= 8)
    14             {
    15                 context.AuditResult = true;
    16                 context.AuditRemark = "允许请假!";
    17             }
    18             else
    19             {
    20                 base.AuditNext(context);
    21             }
    22         }
    23     }
    View Code
     1     public class Charge: AbstractAuditor
     2     {
     3         public override void Audit(ApplyContext context)
     4         {
     5             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
     6             if (context.Hour <= 16)
     7             {
     8                 context.AuditResult = true;
     9                 context.AuditRemark = "允许请假!";
    10             }
    11             else
    12             {
    13                 base.AuditNext(context);
    14             }
    15         }
    16     }
    View Code
     1     public class Manager : AbstractAuditor
     2     {
     3         public override void Audit(ApplyContext context)
     4         {
     5             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
     6             if (context.Hour <= 24)
     7             {
     8                 context.AuditResult = true;
     9                 context.AuditRemark = "允许请假!";
    10             }
    11             else
    12             {
    13                 base.AuditNext(context);
    14             }
    15         }
    16     }
    View Code
     1     public class Chief : AbstractAuditor
     2     {
     3         public override void Audit(ApplyContext context)
     4         {
     5             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
     6             if (context.Hour <= 48)
     7             {
     8                 context.AuditResult = true;
     9                 context.AuditRemark = "允许请假!";
    10             }
    11             else
    12             {
    13                 base.AuditNext(context);
    14                 //....
    15             }
    16         }
    17     }
    View Code
     1     public class CEO : AbstractAuditor
     2     {
     3         public override void Audit(ApplyContext context)
     4         {
     5             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
     6             if (context.Hour <= 96)
     7             {
     8                 context.AuditResult = true;
     9                 context.AuditRemark = "允许请假!";
    10             }
    11             else
    12             {
    13                 base.AuditNext(context);
    14                 //....
    15             }
    16         }
    17     }
    View Code
     1     public class ChiarMan : AbstractAuditor
     2     {
     3         public override void Audit(ApplyContext context)
     4         {
     5             Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
     6             if (context.Hour <= 1000000)
     7             {
     8                 context.AuditResult = true;
     9                 context.AuditRemark = "允许请假!";
    10             }
    11             else
    12             {
    13                 base.AuditNext(context);
    14                 //....
    15             }
    16         }
    17     }
    View Code

    前端调用:

     1                 ApplyContext context = new ApplyContext()
     2                 {
     3                     Id = 1,
     4                     Name = "aaa",
     5                     Hour = 100,
     6                     Description = "我想...",
     7                     AuditResult = false,
     8                     AuditRemark = ""
     9                 };
    10                     //流程的可扩展
    11 
    12                     AbstractAuditor auditor = AuditorBuilder.Build();
    13                     auditor.Audit(context);
    14                     if (!context.AuditResult)
    15                     {
    16                         Console.WriteLine("不干了!");
    17                     }
    18                     //把流程环节逻辑从业务类转移了
    View Code
     1     public class AuditorBuilder
     2     {
     3         /// <summary>
     4         /// 那就反射+配置文件
     5         /// 链子的组成都可以通过配置文件
     6         /// </summary>
     7         /// <returns></returns>
     8         public static AbstractAuditor Build()
     9         {
    10             AbstractAuditor pm = new PM()
    11             {
    12                 Name = "bbb"
    13             };
    14             AbstractAuditor charge = new Charge()
    15             {
    16                 Name = "ccc"
    17             };
    18             AbstractAuditor manager = new Manager()
    19             {
    20                 Name = "ddd"
    21             };
    22             AbstractAuditor chief = new Chief()
    23             {
    24                 Name = "eee"
    25             };
    26             AbstractAuditor ceo = new CEO()
    27             {
    28                 Name = "fff"
    29             };
    30 
    31             pm.SetNext(charge);
    32             charge.SetNext(manager);
    33             //pm.SetNext(manager);
    34             manager.SetNext(chief);
    35             chief.SetNext(ceo);
    36             ceo.SetNext(new ChiarMan()
    37             {
    38                 Name = "ggg"
    39             });
    40             return pm;
    41         }
    42     }
    View Code

    代码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构

    本文参考文档:

    https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

    https://www.cnblogs.com/zhili/p/ChainOfResponsibity.html

    https://www.cnblogs.com/abcdwxc/archive/2007/09/25/905622.html

  • 相关阅读:
    Linux驱动下的platform总线架构(转)
    一生中很值得看的30个故事之一断箭
    学习嵌入式LINUX系统的笔记和体会
    DIY:自己动手做一个迷你 Linux 系统
    linux里面i386 i686 i486 i586代表什么?是什么意思
    菜鸟编译Linux内核
    LINUX核心重编与升级
    ARM 内核移植中常见的错误
    Linux 2.6.19.x 内核编译配置选项简介
    基于S3C2410平台移植Linux 2.6内核指南
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11451460.html
Copyright © 2020-2023  润新知