设计模式之责任链模式

设计模式之责任链模式

在软件设计中使用责任链模式来实现松散耦合,将客户端的请求传递给对象链进行处理。然后链中的对象将自己决定谁将处理请求,以及请求是否需要被发送到链中的下一个对象。


一、JDK中的应用

如JDK中的switch、try-catch中的多个catch块等。

二、举个例子

责任链模式的一个很好的例子是自动提款机。用户输入要分发的金额,然后机器以指定货币的形式分发金额,如50美元、20美元、10美元等。

如果用户输入的数值不是10的倍数,就会抛出错误。我们将使用责任链模式来实现此解决方案。链处理请求的顺序如下图所示。

img

请注意:我们可以在单个程序中轻松实现此解决方案,但这样会增加复杂性,并且是紧耦合的。

所以我们将创建一个分发系统链来分发50美元、20美元和10美元的钞票。

  1. 创建一个货币类来存储需要分发数量
public class Currency {

	private int amount;
	
	public Currency(int amt){
		this.amount=amt;
	}
	
	public int getAmount(){
		return this.amount;
	}
}
  1. 定义抽象处理者接口

它应该有处理请求,以及传递给下一个处理者的抽象方法。like thiis:

public interface DispenseChain {

	void setNextChain(DispenseChain nextChain);
	
	void dispense(Currency cur);
}
  1. 定义具体的处理者,

当然有三个

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()啊
posted @ 2020-11-22 20:33  HeliusKing  阅读(169)  评论(0编辑  收藏  举报