一.职责链设计模式介绍
职责链模式:将能够处理同一类请求的对象连成一条链,使这些对象都有机会处理请求,所提交的请求沿着链传递。从而避免请求的
发送者和接受者之间的耦合关系。链上的对象逐个判断是否有能力处理该请求,如果能则就处理,如果不能,则传给链上的下一个对象处理。
二.职责链模式代码用例
银行ATM取款机就是一个例子,假如银行取款机里面只有100,50,10三种面额的货币,对应着有处理100、50、10元三种面值货币的对象,将这三种对象放在一条链中。当输入取款金额时,先用处理100面额的对象去处理,若金额正好是100的整数倍,则直接处理完结束,若金额不是100的整数倍,则将处理后的金额给链中处理50面额的对象处理,此时的金额若是50的整数倍则处理完便结束,否则将处理后的金额给链中下一个处理10元面额的对象处理,若此时的金额整好是10的整数倍则处理完结束,否则交给默认处理方法处理。
1.先定义一个货币对象Currency
class Currency { private int amount; public Currency(int amt){ this.amount=amt; } public int getAmount(){ return this.amount; } }
2.基本的职责链
基本职责链中应该定义一个给下一个职责链的方法和一个处理具体请求的方法
interface DispenseChain{ void setNextChain(DispenseChain dispenseChain); void process(Currency currency); }
3.链的实现类(处理100元,50元,10元三种情况的具体对象)
class Yuan100Dispense implements DispenseChain{ private DispenseChain chain; @Override public void setNextChain(DispenseChain dispenseChain) { this.chain=dispenseChain; } @Override public void process(Currency currency) { Integer mount=currency.getCurrency(); if(mount>=100){ Integer num100 = mount/100;//100面额货币张数 Integer mount100 = mount%100;//低于100面额的货币值 System.out.println("取出100面额货币张数:"+num100); if(mount100!=0){ this.chain.process(new Currency(mount100)); } }else{ this.chain.process(new Currency(mount)); } } }
class Yuan50Dipense implements DispenseChain{ private DispenseChain chain; @Override public void setNextChain(DispenseChain dispenseChain) { this.chain=dispenseChain; } @Override public void process(Currency currency) { Integer mount=currency.getCurrency(); if(mount>=50){ Integer num50 = mount/50; Integer mount50 = mount%50; System.out.println("取出50元面额货币张数:"+num50); if(mount50!=0){ this.chain.process(new Currency(mount50)); } }else{ this.chain.process(new Currency(mount)); } } }
class Yuan10Dispense implements DispenseChain{ private DispenseChain chain; @Override public void setNextChain(DispenseChain dispenseChain) { this.chain = dispenseChain; } @Override public void process(Currency currency) { int mount = currency.getCurrency(); if(mount>=10){ Integer num10 = mount/10;//10元面额货币张数 Integer mount10 = mount%10;//低于10元面额的货币值 System.out.println("取出10元面额货币张数:"+num10); if(mount10!=0){ this.chain.process(new Currency(mount10)); } }else{ this.chain.process(new Currency(mount)); } } }
4.ATM客户端测试职责链模式
public class ATMDispenseChain { private DispenseChain c1; public ATMDispenseChain() { // initialize the chain this.c1 = new Yuan100Dispense(); DispenseChain c2 = new Yuan50Dispense(); DispenseChain c3 = new Yuan10Dispense(); // 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)); } } }
三.职责链模式需要注意的问题
1.职责链中的每个对象都要有下一个处理对象的引用。
2.设计职责链时,要通盘考虑处理各种情况的对象,以防遍历完链中所有处理对象后仍然没有能够处理该问题的方法,以防抛出异常。
3.当链中的对象非常多时,需要权衡维护众多实现类所带来的成本。
Java中用到职责链模式的类:java.util.logging.Logger#log()、javax.servlet.Filter#doFilter()。