包装责任链功能比直接在类中更好吗?

时间:2018-01-12 03:47:59

标签: java design-patterns architecture software-design design-principles

我一直专注于学习编程原则和模式,但我发现的责任链示例似乎都与其他原则/模式相矛盾。将sethandler和nexthandler直接放在一个不仅仅是那个的类中似乎是一个非常糟糕的主意。

在尝试学习以前的模式时,我确实找到了许多不切实际的简单例子,所以起初我认为我发现的例子就是这种情况。但经过大量的谷歌搜索后,我找不到任何接近我想象的例子。所以我开始检查文章,我甚至找不到关于处理程序功能应该如何与使用它的类分开的简短句子。

让我想到,自从它只有两种方法以来,在一个具体的类上拥有责任链并不是一件大事。

但同样,这似乎真的非常错误。如果你想在其他地方以非责任链模式方式使用这个类,你会做什么,因为责任链功能直接构建在类中。

在浏览了有关责任链的google文章的页面和页面之后,我最终找到了一个用包装类实现功能的示例。它几乎将一个具体的类委托给一个包装类,这样就可以使用具体的类而不需要责任链功能。

所以我的问题是..责任链原则的大多数现实世界实现会使用包装类还是直接在类中?也许我只是误解了这种模式实际上会用到的情况?

为了真正能够比较和理解每种方法,我决定使用这两种方法编写自己的例子。下面我粘贴了两者中最重要的部分并链接到完整的示例。

Normal Method

ILoanApprover

interface ILoanApprover{
  public void approveLoan(Loan loan);
  public void setNextApprover(ILoanApprover nextApprover);
}

员工

abstract class Employee implements ILoanApprover{
  protected ILoanApprover nextApprover;
  protected int approvalLimit;
  private String rank;

  public Employee(String rank, int approvalLimit){
    this.rank = rank;
    this.approvalLimit = approvalLimit;
  }

  @Override
  public void setNextApprover(ILoanApprover nextApprover){
    this.nextApprover = nextApprover;
  }
  @Override
  public void approveLoan(Loan loan){

    if (approvalLimit > loan.getAmount() ){
      System.out.println(rank+" approves loan of "+loan.getAmount());
      return;
    }
    nextApprover.approveLoan(loan);
  }
}

管理器

class Manager extends Employee{
  public Manager(){
    super("Manager", 5000);
  }
}

贷款

class Loan{
  private int amount;
  public Loan(int amount){
    this.amount = amount;
  }
  public int getAmount(){ return amount; }
}

Wrapper Method

ILoanApprover

interface ILoanApprover{
  public boolean approveLoan(Loan loan);
}

ILoanHandler

interface ILoanHandler{
  public void setNextLoanHandler(ILoanHandler nextHandler);
  public void handleLoanApproval(Loan loan);
}

LoanHandler

class LoanHandler implements ILoanHandler{

  protected ILoanApprover approver;
  protected ILoanHandler nextHandler;

  public LoanHandler(ILoanApprover approver){
    this.approver = approver;
  }

  @Override
  public void setNextLoanHandler(ILoanHandler nextHandler){
    this.nextHandler = nextHandler;
  }

  @Override
  public void handleLoanApproval(Loan loan){

    boolean approved = approver.approveLoan(loan);

    if (!approved && nextHandler != null){
      nextHandler.handleLoanApproval(loan);
    }
  }
}

员工

abstract class Employee implements ILoanApprover{
  protected int approvalLimit;
  private String rank;
  public Employee(String rank, int approvalLimit){
    this.rank = rank;
    this.approvalLimit = approvalLimit;
  }

  @Override
  public boolean approveLoan(Loan loan){

    if (approvalLimit > loan.getAmount() ){
      System.out.println(rank+" approves loan of "+loan.getAmount());
      return true;
    }

    return false;
  }
}

管理器

class Manager extends Employee{
  public Manager(){
    super("Manager", 5000);
  }
}

贷款

class Loan{
  private int amount;
  public Loan(int amount){
    this.amount = amount;
  }
  public int getAmount(){ return amount; }
}

主要

ILoanHandler man = new LoanHandler(new Manager());

1 个答案:

答案 0 :(得分:0)

嗯,虽然我认为直觉是正确的,但我有几点:

  • COR模式并没有精确指定如何在实际代码中实现它,因为有很多方法可以做到这一点(直接在具体类中,继承,泛型,包含,组成等),我认为这种模式试图描述一个想法的本质,忽略细节。

  • 使用wikipedia article的术语:模式最重要的方面是Handler接口。给定一个稳定且定义良好的界面,您可以实现您的 Receiver课程有多种方式,选择取决于其他注意事项。您提到了一个这样的考虑,即可重用性,并且您可以通过单一责任原则(SRP)来指导:因为在您的特定情况下,Employee类提示应该管理的类员工详细信息,然后贷款审批责任可能应该完全委托给LoanApproval类,这样Employee没有直接依赖LoanApproval(因此没有实现{{1} }})。为此,您可以遵循 Clean Architecture 原则,其中用例(例如ILoanApprover)应该依赖于实体(例如LoanApprovalEmployee)而不是反过来(事实上,更准确地说,依赖于实体的隔离接口,这是一个单独的问题)。另一种表达方式是说Loan可能不应该充当EmployeeReciever。鉴于此,它可能(或者现在可能不是!),您希望在COR模式之外使用Sender,这对于再次分离是一个很好的论据,无论是为了重用还是为了删除重复逻辑。你可以用上面提到的一些方法做到这一点,例如继承,泛型等......

  • 考虑上述问题的另一种相关方式是,当您需要为LoanApproval添加其他任务/用例时,请考虑设计会发生什么。 Employee将需要实现更多的Employee接口,其中一些可能具有冲突的函数名称等,这就是你陷入混乱的地方,结果就是你有一个不断扩展的核心类责任越来越多。

所以,你绝对正确考虑去除责任,重用性和删除重复代码,并且有不同的方法可以做到这一点,但我认为这些问题与COR模式是正交的,这纯粹是关于能够在运行时动态地将任务链接在一起的优势。

P.S。在现实世界中,我看到这种模式以各种可怕的方式实现......有时使用现实世界作为指导是没有用的!