设计模式之责任链模式
设计模式之责任链模式
在软件设计中使用责任链模式来实现松散耦合,将客户端的请求传递给对象链进行处理。然后链中的对象将自己决定谁将处理请求,以及请求是否需要被发送到链中的下一个对象。
一、JDK中的应用
如JDK中的switch、try-catch中的多个catch块等。
二、举个例子
责任链模式的一个很好的例子是自动提款机。用户输入要分发的金额,然后机器以指定货币的形式分发金额,如50美元、20美元、10美元等。
如果用户输入的数值不是10的倍数,就会抛出错误。我们将使用责任链模式来实现此解决方案。链处理请求的顺序如下图所示。
请注意:我们可以在单个程序中轻松实现此解决方案,但这样会增加复杂性,并且是紧耦合的。
所以我们将创建一个分发系统链来分发50美元、20美元和10美元的钞票。
- 创建一个货币类来存储需要分发数量
public class Currency {
private int amount;
public Currency(int amt){
this.amount=amt;
}
public int getAmount(){
return this.amount;
}
}
- 定义抽象处理者接口
它应该有处理请求,以及传递给下一个处理者的抽象方法。like thiis:
public interface DispenseChain {
void setNextChain(DispenseChain nextChain);
void dispense(Currency cur);
}
- 定义具体的处理者,
当然有三个
public class Dollar50Dispenser implements DispenseChain {
private DispenseChain chain;
@Override
public void setNextChain(DispenseChain nextChain) {
this.chain=nextChain;
}
@Override
public void dispense(Currency cur) {
if(cur.getAmount() >= 50){
int num = cur.getAmount()/50;
int remainder = cur.getAmount() % 50;
System.out.println("Dispensing "+num+" 50$ note");
if(remainder !=0) this.chain.dispense(new Currency(remainder));
}else{
this.chain.dispense(cur);
}
}
}
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);
}
}
}
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);
}
}
}
这里通过三个实现类总结两点:
每个具体的处理者,都实现了dspense,但他们可以选择如何处理。这里是部分处理。
当未处理,或完全处理,就必须要交给链上的下一个处理者了。
所以每个处理者,拥有下个处理者的引用。这里使用的是组合。
三、客户端调用
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.
四、 小结
客户端并不知道链上的了哪个Handler将会处理请求,
链上的每个处理者都实现了抽象的处理方法,但如何处理,不做具体要求。不过既然称之为责任链模式,一般处理不了或部分处理时。总要交个下一个处理者去继续处理。
为了传递请求,每个处理者都拥有对下个处理者的引用。这是种组合模式。
典型应用:
- java.util.logging.Logger#log()
- javax.servlet.Filter#doFilter()啊
你所看得到的天才不过是在你看不到的时候还在努力罢了!