设计模式之-责任链(Chain of responsibility )

责任是用来实现解耦合软件设计,来自客户端的请求被传递到链条的对象来处理他们然后该链中的对象将自己决定处理请求是否需要请求发送给链中的下一个处理对象没有下一个对象。

让我们来看看责任链模式的JDK例子,然后我们将着手实现这一模式的例子我们知道,我们可以在一个try-catch块代码中的多个catch块在这里,每个catch块都是一个处理器来处理特定的异常所以,当任何异常在try块中发生发送给第一个catch块来处理如果在catch块不能处理它转发,即下一个catch块请求下一个对象如果连最后的catch块不能处理它那么这个异常将会抛出到链的调用程序之外


一个责任链模式一个很好的例子ATM处理用户输入将被分配总计数 ,机器根据货币票额信息分类,例如$ 50$ 20$ 10等。如果用户输入的量不是10的倍数,则会引发错误我们将使用责任链模式来实现这个解决方案将处理相同的顺序如下图



需要注意的是,我们可以在一个程序中很容易地实现这种解决方案,但随后复杂性将增加,程序紧密地耦合因此,我们将创建一个链式系统来分发处理,以$ 50$ 20$ 10为单位进行处理


基类与接口设计:


我们创建Currency 类,用于存储总计数,供链式分发处理参考

package com.journaldev.design.chainofresponsibility;
 
public class Currency {
 
    private int amount;
     
    public Currency(int amt){
        this.amount=amt;
    }
     
    public int getAmount(){
        return this.amount;
    }
}

基类接口实现应该有一个定义在链中的下一个处理器,并且将处理该请求方法的方法我们的自动取款机分发接口会像下面一样


package com.journaldev.design.chainofresponsibility;
 
public interface DispenseChain {
 
    void setNextChain(DispenseChain nextChain);
     
    void dispense(Currency cur);
}

具体链式实现:

我们需要创建不同的实现类来分别实现DispenseChain接口,并且实现对应分发方法,由于我们开发的系统处理的是三种货币单位,因此我们需要三个实现类


package com.journaldev.design.chainofresponsibility;
 
public class Dollar50Dispenser implementsDispenseChain {
 
    privateDispenseChain chain;
     
    @Override
    publicvoid setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }
 
    @Override
    publicvoid dispense(Currency cur) {
        if(cur.getAmount() >=50){
            intnum = cur.getAmount()/50;
            intremainder = cur.getAmount() % 50;
            System.out.println("Dispensing "+num+" 50$ note");
            if(remainder !=0)this.chain.dispense(newCurrency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
 
}


package com.journaldev.design.chainofresponsibility;
 
public class Dollar20Dispenser implements DispenseChain{
 
    private DispenseChain chain;
     
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }
 
    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount() >= 20){
            int num = cur.getAmount()/20;
            int remainder = cur.getAmount() % 20;
            System.out.println("Dispensing "+num+" 20$ note");
            if(remainder !=0) this.chain.dispense(new Currency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
 
}

package com.journaldev.design.chainofresponsibility;
 
public class Dollar10Dispenser implements DispenseChain {
 
    private DispenseChain chain;
     
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }
 
    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount() >= 10){
            int num = cur.getAmount()/10;
            int remainder = cur.getAmount() % 10;
            System.out.println("Dispensing "+num+" 10$ note");
            if(remainder !=0) this.chain.dispense(new Currency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
 
}

这里要注意重要一点是分配方法的实现你会发现,每一个执行正试图处理该请求,并根据处理数量,可能处理一部分或完全处理如果它不能够完全处理它时,它发送请求来处理剩余的请求下一个处理器如果处理器能够处理任何事情,只是转发相同的请求到下一个


链条创建:

这是一个非常重要的一步,我们创建链条时要非常小心否则处理器可能不会得到任何请求都没有。例如我们的实现中,如果我们继续第一处理器Dollar10Dispenser然后Dollar20Dispenser,则该请求将不会被转发到所述第二处理器和所述链条将变得无用

这里是我们的ATM提款机执行处理用户请求的金额


package com.journaldev.design.chainofresponsibility;
 
import java.util.Scanner;
 
public class ATMDispenseChain {
 
    private DispenseChain c1;
 
    public ATMDispenseChain() {
        // initialize the chain
        this.c1 = new Dollar50Dispenser();
        DispenseChain c2 = new Dollar20Dispenser();
        DispenseChain c3 = new Dollar10Dispenser();
 
        // set the chain of responsibility
        c1.setNextChain(c2);
        c2.setNextChain(c3);
    }
 
    public static void main(String[] args) {
        ATMDispenseChain atmDispenser = new ATMDispenseChain();
        while (true) {
            int amount = 0;
            System.out.println("Enter amount to dispense");
            Scanner input = new Scanner(System.in);
            amount = input.nextInt();
            if (amount % 10 != 0) {
                System.out.println("Amount should be in multiple of 10s.");
                return;
            }
            // process the request
            atmDispenser.c1.dispense(new Currency(amount));
        }
 
    }
 
}

运行程序会得到下面结果:


Enter amount to dispense
530
Dispensing 10 50$ note
Dispensing 1 20$ note
Dispensing 1 10$ note
Enter amount to dispense
100
Dispensing 2 50$ note
Enter amount to dispense
120
Dispensing 2 50$ note
Dispensing 1 20$ note
Enter amount to dispense
15
Amount should be in multiple of 10s.


类之间关系图:


知识要点总结:

1,客户端不知道链中的一部分将是对请求的处理,它会请求发送到所述第一对象例如我们的程序       ATMDispenseChain不知道正在处理以分配所输入的的要求
2,链中的每个对象都有它自己的实现来处理请求,无论是全部或部分,或将其传送到下一个对象
3,在链中的每个对象应具有参考链中的下一对象转发java的组合物取得的请求
4,谨慎小心处理是非常重要的,否则可能是请求将不会被转发到一个特定的处理器或者有链中没有对象谁能够处理请求的情况。 在我的实现我已经加入检查用户输入的金额,以确保它得到所有的处理器完全处理,但我们可能不会检查它并抛出异常,
如果请求到达的最后一个对象,并没有其它目的转发请求这是一个设计决策
5,责任链模式很好的实现失去联结,但它自带的权衡有很多实现类和维修问题,如果大部分的代码所有实现共同


原文链接:http://www.journaldev.com/1617/chain-of-responsibility-design-pattern-in-java



posted @ 2014-09-11 23:58  HappyCode002  阅读(333)  评论(0编辑  收藏  举报