包装责任链功能是否比直接在 class 中更好?
Is it better to wrap chain of responsibility functionality than have it directly in a class?
我一直专注于学习编程原则和模式,但我发现的责任链示例似乎都与其他示例相矛盾 principles/patterns。将 sethandler 和 nexhandler 直接放置在 class 中会做更多的事情,这似乎是一个非常非常糟糕的主意。
在尝试学习以前的模式时,我确实发现了很多不切实际的简单示例,所以起初我认为我找到的示例就是这种情况。但是经过大量谷歌搜索后,我找不到任何接近我想象的例子。因此,我开始查看文章,但我什至找不到关于处理程序功能应如何与使用它的 class 分开的简短句子。
这让我想到也许在具体的 class 上建立责任链并不是什么大不了的事,因为它只有两种方法。
但是,这似乎真的是错误的。如果您想在其他地方以非责任链模式的方式使用 class,您会怎么做,因为责任链功能直接内置于 class.
在浏览了一页又一页关于责任链的 google 篇文章后,我没有找到关于这个主题的任何内容,我最终找到了一个使用包装器 class 实现功能的示例。它几乎将具体的 class 委托给包装器 class 以便仍然可以使用具体的 class 而无需责任链功能。
所以我的问题是.. 大多数现实世界中责任链原则的实施会使用包装器 class 还是直接在 class 中?也许我只是误解了这种模式实际使用的情况?
为了真正能够比较和理解每种方法,我决定使用这两种方法编写自己的示例。下面我粘贴了两者最重要的部分并链接到完整的示例。
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);
}
贷款处理程序
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());
嗯,虽然我觉得直觉是对的,但我有几点:
COR 模式没有具体说明如何在实际代码中实现它,因为有很多方法可以做到这一点(直接在具体的class, inheritance, generics, containment, composition etc),我认为这个模式试图描述一个想法的本质,忽略了细节。
使用 wikipedia article 的术语:该模式最重要的方面是 Handler
接口。给定一个稳定且定义良好的接口,您可以实现您的
Receiver
class 有多种选择,该选择取决于 其他考虑因素 。您提到了一个这样的考虑因素,即可重用性,因此您可以遵循单一责任原则(SRP):因为在您的特定情况下, Employee
class 暗示了一个class 应该管理员工详细信息,那么贷款审批责任可能应该完全委托给 LoanApproval
class,这样 Employee
就没有直接依赖于 LoanApproval
(因此不实现 ILoanApprover
)。为此,您可以遵循 清洁架构 原则,其中用例(例如 LoanApproval
)应依赖于实体(例如 Employee
和 Loan
) 而不是相反(事实上,更准确地说,依赖于实体的 segregated 接口,这是一个单独的问题)。另一种表达方式是说 Employee
可能不应该充当 Reciever
或 Sender
。鉴于此,您可能(现在可能不会!)希望在 COR 模式之外使用 LoanApproval
,这是再次分离的一个很好的论据,既可重用又可删除重复逻辑。您可以使用上面提到的一些方法来做到这一点,例如继承、泛型等...
考虑上述问题的另一种相关方式是考虑当您需要为 Employee
添加其他 tasks/use-cases 时您的设计会发生什么。 Employee
将需要实现更多 Handler
接口,其中一些可能有冲突的函数名称等,这就是你陷入困境的地方,结果是你有一个核心 class随着越来越多的责任不断扩展。
因此,您考虑解耦责任、可重用性和删除重复代码绝对是正确的,并且有不同的方法可以做到这一点,但我认为这些问题与 COR 模式正交,即纯粹是关于能够在运行时动态地将任务链接在一起的优势。
P.S。在现实世界中,我已经看到这种模式以各种可怕的方式实施......有时以现实世界为指导并没有帮助!
我一直专注于学习编程原则和模式,但我发现的责任链示例似乎都与其他示例相矛盾 principles/patterns。将 sethandler 和 nexhandler 直接放置在 class 中会做更多的事情,这似乎是一个非常非常糟糕的主意。
在尝试学习以前的模式时,我确实发现了很多不切实际的简单示例,所以起初我认为我找到的示例就是这种情况。但是经过大量谷歌搜索后,我找不到任何接近我想象的例子。因此,我开始查看文章,但我什至找不到关于处理程序功能应如何与使用它的 class 分开的简短句子。
这让我想到也许在具体的 class 上建立责任链并不是什么大不了的事,因为它只有两种方法。
但是,这似乎真的是错误的。如果您想在其他地方以非责任链模式的方式使用 class,您会怎么做,因为责任链功能直接内置于 class.
在浏览了一页又一页关于责任链的 google 篇文章后,我没有找到关于这个主题的任何内容,我最终找到了一个使用包装器 class 实现功能的示例。它几乎将具体的 class 委托给包装器 class 以便仍然可以使用具体的 class 而无需责任链功能。
所以我的问题是.. 大多数现实世界中责任链原则的实施会使用包装器 class 还是直接在 class 中?也许我只是误解了这种模式实际使用的情况?
为了真正能够比较和理解每种方法,我决定使用这两种方法编写自己的示例。下面我粘贴了两者最重要的部分并链接到完整的示例。
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);
}
贷款处理程序
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());
嗯,虽然我觉得直觉是对的,但我有几点:
COR 模式没有具体说明如何在实际代码中实现它,因为有很多方法可以做到这一点(直接在具体的class, inheritance, generics, containment, composition etc),我认为这个模式试图描述一个想法的本质,忽略了细节。
使用 wikipedia article 的术语:该模式最重要的方面是
Handler
接口。给定一个稳定且定义良好的接口,您可以实现您的Receiver
class 有多种选择,该选择取决于 其他考虑因素 。您提到了一个这样的考虑因素,即可重用性,因此您可以遵循单一责任原则(SRP):因为在您的特定情况下,Employee
class 暗示了一个class 应该管理员工详细信息,那么贷款审批责任可能应该完全委托给LoanApproval
class,这样Employee
就没有直接依赖于LoanApproval
(因此不实现ILoanApprover
)。为此,您可以遵循 清洁架构 原则,其中用例(例如LoanApproval
)应依赖于实体(例如Employee
和Loan
) 而不是相反(事实上,更准确地说,依赖于实体的 segregated 接口,这是一个单独的问题)。另一种表达方式是说Employee
可能不应该充当Reciever
或Sender
。鉴于此,您可能(现在可能不会!)希望在 COR 模式之外使用LoanApproval
,这是再次分离的一个很好的论据,既可重用又可删除重复逻辑。您可以使用上面提到的一些方法来做到这一点,例如继承、泛型等...考虑上述问题的另一种相关方式是考虑当您需要为
Employee
添加其他 tasks/use-cases 时您的设计会发生什么。Employee
将需要实现更多Handler
接口,其中一些可能有冲突的函数名称等,这就是你陷入困境的地方,结果是你有一个核心 class随着越来越多的责任不断扩展。
因此,您考虑解耦责任、可重用性和删除重复代码绝对是正确的,并且有不同的方法可以做到这一点,但我认为这些问题与 COR 模式正交,即纯粹是关于能够在运行时动态地将任务链接在一起的优势。
P.S。在现实世界中,我已经看到这种模式以各种可怕的方式实施......有时以现实世界为指导并没有帮助!