实例讲解C#中的职责链模式

2020-07-09 12:01:57王振洲

大家好,欢迎来到老胡的博客,今天我们继续了解设计模式中的职责链模式,这是一个比较简单的模式。跟往常一样,我们还是从一个真实世界的例子入手,这样大家也对这个模式的应用场景有更深刻的理解。

一个真实的栗子

作为上班族,相信大家对请假都不陌生,每个公司都有自己请假的流程,稍微讲究点的公司还会有细致的规定,比如,3天以内的假期,小组长有权力批准,3天以上的假期就要找更高级别的领导批准。这种制度就是典型的权力越大职责越大——毕竟,批长假的职责只在高级主管那里存在。

除了规定出这样细致的要求之外,大部分公司还有用软件实现了请假流程,当请假人员提出请假申请的时候,会依据请假天数,转发给具有权限的人员审批,让我们看看这个系统的代码实现吧。

请假系统实现

在这个系统中,我们假定:

小组长可以审批3天以内的请假请求 部门经理可以审批5天以内的请假请求 10天以内的请假请求只有老板才能审批 我们同时假定,这个公司的管理层非常人性化,请假都能得到批准,除非大于10天,因为这种情况没人可以审批 

请假申请

这是最简单的类,封装了请假天数和请假申请人

class VacationRequest
{
  public int DayNum { get; set; }
  public string RequesterName { get; set; }
}

假期审批者

首先创建一个抽象类,假期审批者,封装假期审批的基本逻辑,即,如果当前人员有权限审批当前假期申请,就处理

abstract class VacationApprover
{    
  protected VacationApprover(int dayCanHandle)
  {
    DayCanHandle = dayCanHandle;
  }

  public int DayCanHandle { get; protected set; }

  public void HandleVacationRequest(VacationRequest request)
  {
    if (request.DayNum <= DayCanHandle)
    {
      DoHandleVacationRequest(request);
    }
  }

  protected abstract void DoHandleVacationRequest(VacationRequest request);
}

当然,抽象类只需要确定算法骨架,限定只有当前人员能处理这个请求的时候,才进行审批工作,至于具体的审批实现,留给子类自己去覆盖,这种在父类固定算法骨架,暴露部分覆盖点给子类的做法,就是之前我们提到过的TemplateMethod模式

具体假期审批者

小组长,部门经理,老板,都在这里创建,他们分别处理能审批3、5、10天的请假申请

class TeamLeader : VacationApprover
{
  private const int DAY_CAN_HANDLE_TEAMLEADER = 3;
  public TeamLeader() : base(DAY_CAN_HANDLE_TEAMLEADER) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now team leader handle this request");
    Console.WriteLine("Team leader accept this request");
  }
}

class DepartmentLeader : VacationApprover
{
  private const int DAY_CAN_HANDLE_DEPARTMENTLEADER = 5;
  public DepartmentLeader() : base(DAY_CAN_HANDLE_DEPARTMENTLEADER) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now department leader handle this request");
    Console.WriteLine("Department leader accept this request");
  }
}

class Boss : VacationApprover
{
  private const int DAY_CAN_HANDLE_BOSS = 10;
  public Boss() : base(DAY_CAN_HANDLE_BOSS) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now boss handle this request");
    Console.WriteLine("Boss accept this request");
  }
}