• 设计模式之责任链模式


    设计模式之责任链模式

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


    一、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()啊
  • 相关阅读:
    HDU 4763 Theme Section(KMP+枚举公共前后缀)
    HDU 3613 Best Reward(扩展KMP求前后缀回文串)
    HDU 3613 Best Reward(manacher求前、后缀回文串)
    扩展KMP模板
    Vue
    Vue
    css 文本换行 文本溢出隐藏用省略号表示剩下内容
    sublime 神一样的插件
    markdown
    css 居中布局
  • 原文地址:https://www.cnblogs.com/heliusKing/p/14021192.html
Copyright © 2020-2023  润新知