职责链模式

104 阅读3分钟

背景

当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。我们可以考虑将多个对象组成一条职责链,然后按照它们在职责链上的顺序一个一个找出到底应该谁来负责处理

登场角色

处理者 Handler

Handler角色决定了处理请求的接口。Handler角色知道“下一个处理者”是谁,如果自己无法处理请求,它会将请求转给“下一个处理者”,“下一个处理者”也是Handler角色。

具体的处理者 ConcreteHanlder

ConcreteHanlder是处理请求的具体角色

请求者 Client

Client 角色是向第一个ConcreteHanlder角色发送请求的角色

类图

实例代码

这里是一个模拟处理问题的职责链,使用数字表示解决的问题,根据其数据进行固定的处理

Support 抽象类 相当于Handler

public abstract class Support {
    private String name;

    // 自己聚合自己
    private Support next;

    public Support(String name) {
        this.name = name;
    }

    /**
     * 设置职责链
     * @param next
     * @return
     */
    public Support setNext(Support next) {
        this.next = next;
        return next;
    }

    /**
     * 决定处理逻辑
     * @param trouble
     */
    public void support(Trouble trouble) {
        if (solve(trouble)) {
            done(trouble);
        } else if (this.next != null) {
            this.next.support(trouble);
        } else {
            fail(trouble);
        }
    }

    /**
     * 使用模板方法模式 让子类重写solve方法,父类决定调用逻辑
     * @param trouble
     * @return
     */
    public abstract boolean solve(Trouble trouble);

    public void done(Trouble trouble) {
        System.out.println("solve problem " + trouble + "by" + this.name);
    }

    public void fail(Trouble trouble) {
        System.out.println("fail solve problem " + trouble);
    }
}

Support 具体的实现类 相当于ConcreteHandler

NoneSupport类:什么也不做的类

/**
 * 什么也不做
 */
public class NoneSupport extends Support{

    public NoneSupport(String name) {
        super(name);
    }

    @Override
    public boolean solve(Trouble trouble) {
        return false;
    }
}

OddSupport类:处理奇数的类

/**
 * 处理奇数的 handler
 */
public class OddSupport extends Support {

    public OddSupport(String name) {
        super(name);
    }

    @Override
    public boolean solve(Trouble trouble) {
        int number = trouble.getNumber();

        if (number % 2 == 1) {
            return true;
        }
        return false;
    }
}

SpecialSupport类:处理固定数字的类

/**
 * 处理固定数字的handler
 */
public class SpecialSupport extends Support{
    private int special;

    public SpecialSupport(String name, int special) {
        super(name);
        this.special = special;
    }

    @Override
    public boolean solve(Trouble trouble) {
        int number = trouble.getNumber();
        if (number == special) {
            return true;
        }
        return false;
    }
}

LimitSupport类:处理固定范围的类

/**
 * 处理固定范围的 handler
 */
public class LimitSupport extends Support{
    private int limit;

    public LimitSupport(String name, int limit) {
        super(name);
        this.limit = limit;
    }


    @Override
    public boolean solve(Trouble trouble) {
        int number = trouble.getNumber();
        return number < limit;
    }
}

Main 类

public class Main {
    public static void main(String[] args) {
        // 创建Handler
        Support alice = new NoneSupport("Alice");
        Support bob = new LimitSupport("Bob", 100);
        Support charlie = new SpecialSupport("Charlie", 429);
        Support diana = new LimitSupport("Diana", 200);
        Support elmo = new OddSupport("Elmo");
        Support fred = new LimitSupport("Fred", 300);

        // 设置职责链
        alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);


        for (int i = 0; i < 500; i+=33) {
            alice.support(new Trouble(i));
        }
    }
}

功能分析

  1. 弱化了发出请求的人和处理请求的人之间的关系,Client角色 向第一个 ConcreteHandler 角色发出请求,然后在职责链中进行传播,不必让某一个固定的Hanlder 处理固定的请求;
  2. 专注自己的工作,每个ConcreteHandler 角色都专注于自己所负责的处理;
  3. 推卸请求可能会导致延迟,如果追求响应速度,那么要考虑不要使用职责链模式;