责任链模式

简介

Advoid coupling the sender of a reuest to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

责任链模式(Chain of Responsibility) 是行为型设计模式之一,其将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。

主要解决

责任链模式 解耦了请求与处理,客户只需将请求发送到链上即可,无需关心请求的具体内容和处理细节,请求会自动进行传递直至有节点对象进行处理。

优缺点

优点

  • 解耦了请求与处理;
  • 请求处理者(节点对象)只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一级节点对象;
  • 具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果;
  • 链路结构灵活,可以通过改变链路结构动态地新增或删减责任;
  • 易于扩展新的请求处理类(节点),符合 开闭原则

缺点

  • 责任链路过长时,可能对请求传递处理效率有影响;
  • 如果节点对象存在循环引用时,会造成死循环,导致系统崩溃;

使用场景

  • 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定;
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
  • 可动态指定一组对象处理请求;

使用场景

首先来看下 责任链模式 的通用 UML 类图:

责任链模式

从 UML 类图中,我们可以看到,责任链模式 主要包含两种角色:

  • 抽象处理者(Handler):定义一个请求处理的方法,并维护一个下一个处理节点 Handler 对象的引用;
  • 具体处理者(ConcreteHandler):对请求进行处理,如果不感兴趣,则进行转发;

以下是 责任链模式 的通用代码:

class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        handlerA.setnextHanlder(handlerB);
        handlerA.handleRequest("requestB");
    }

    static abstract class Handler {
        protected Handler mNextHandler;

        public void setnextHanlder(Handler successor) {
            this.mNextHandler = successor;
        }

        public abstract void handleRequest(String request);
    }

    static class ConcreteHandlerA extends Handler {

        @Override
        public void handleRequest(String request) {
            if ("requestA".equals(request)) {
                System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request));
                return;
            }
            if (this.mNextHandler != null) {
                this.mNextHandler.handleRequest(request);
            }
        }
    }
    static class ConcreteHandlerB extends Handler {

        @Override
        public void handleRequest(String request) {
            if ("requestB".equals(request)) {
                System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request));
                return;
            }
            if (this.mNextHandler != null) {
                this.mNextHandler.handleRequest(request);
            }
        }
    }
}

上面的代码中,其实我们把消息硬编码为String类型,而真实业务中,消息是具备多样性的,可以是intString或者是自定义类型····因此,我们可以在上面代码中的基础上,将消息类型进行抽象Request,增强了消息的包容性。

:责任链模式 的本质是:解耦请求与处理,让请求在处理链中能进行传递与被处理;理解 责任链模式 应当理解的是其模式(道)而不是其具体实现(术),责任链模式 的独到之处是其将节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动了起来。因此,上面的通用代码中,把请求硬编码为String,是为了更加清晰描述 责任链模式 的链式组成与请求传递实现结构原理,而下面内容所要讲述的,其实更多地是基于“术”的层面,如何让 责任链模式 更加完善。

其 UML 类图如下所示:

责任链模式

代码如下所示:

class Client {
    public static void main(String[] args) {
        // 来一个具体处理者A
        Handler handlerA = new ConcreteHandlerA(new ConcreteRequest("requestA"));
        // 来一个具体处理者B
        Handler handlerB = new ConcreteHandlerB(new ConcreteRequest("requestB"));
        // A的下一节点为B
        handlerA.setNextHandler(handlerB);

        // 来一个消息:requestA
        Request request = new ConcreteRequest("requestA");
        // 将消息交由具体处理者A
        handlerA.handleRequest(request);

        System.out.println("------------------------");

        // 来一个消息:requestB
        request = new ConcreteRequest("requestB");
        // 将消息交由具体处理者A
        handlerA.handleRequest(request);

        System.out.println("------------------------");

        // 来一个消息:requestC
        request = new ConcreteRequest("requestC");
        // 将消息交由具体处理者A
        handlerA.handleRequest(request);
    }

    // 抽象消息
    static abstract class Request {
        private T mRequest;

        public Request(T request) {
            this.mRequest = request;
        }

        public T getRequest() {
            return this.mRequest;
        }

        @Override
        public String toString() {
            return this.mRequest.toString();
        }

        public abstract boolean isSame(Request request);
    }

    // 具体消息
    static class ConcreteRequest extends Request {

        public ConcreteRequest(String request) {
            super(request);
        }

        @Override
        public boolean isSame(Request request) {
            return this.getRequest().equals(request.getRequest());
        }
    }

    // 抽象处理者
    static abstract class Handler {
        private Handler mNextHandler;
        private Request mRequest;

        public Handler(Request request) {
            this.mRequest = request;
        }

        public void setNextHandler(Handler successor) {
            this.mNextHandler = successor;
        }

        public final void handleRequest(Request request) {
            do {
                if (this.mRequest.isSame(request)) {
                    this.handle(request);
                    break;
                }
                if (this.mNextHandler != null) {
                    this.mNextHandler.handleRequest(request);
                    break;
                }
                System.out.println("No Handlers can handle this request: " + request);
            } while (false);
        }

        protected abstract void handle(Request request);

    }

    // 具体处理者A
    static class ConcreteHandlerA extends Handler {

        public ConcreteHandlerA(Request request) {
            super(request);
        }

        @Override
        protected void handle(Request request) {
            System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request));
        }
    }

    // 具体处理者B
    static class ConcreteHandlerB extends Handler {

        public ConcreteHandlerB(Request request) {
            super(request);
        }

        @Override
        protected void handle(Request request) {
            System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request));
        }
    }
}

运行结果如下:

ConcreteHandlerA deal with request: requestA
------------------------
ConcreteHandlerB deal with request: requestB
------------------------
No Handlers can handler this request: requestC

责任链模式 的本质是解耦请求和处理,上面的代码抽象了请求Request和处理Hanlder,已经很完善了,但是还可以更加完善。因为 责任链模式 具备链式结构,而上面代码中,我们看到,负责组装链式结构的角色是客户端,当链式结构较长时,客户端的工作会非常繁琐,并且客户端代码相对臃肿,且后续更改处理者或消息类型时,都必须在客户端中进行修改,不符合 开闭原则。产生这些问题的原因就是因为链式结构的组装过于复杂,而对于复杂结构的创建,很自然我们就会想到 建造者模式,使用 建造者模式,我们完全可以对客户端指定的处理节点对象进行自动链式组装,客户只需指定处理节点对象,其他任何事情都无需关心,并且客户指定的处理节点对象顺序不同,构造出来的链式结构也随之不同。

具体代码如下:

class Client {
    public static void main(String[] args) {
        Handler.Builder builder = new Handler.Builder();
        List> handlers = makeHanlders();
        for (Handler handler : handlers) {
            builder.addHandler(handler);
        }
        Handler firstHandler = builder.build();
        for (int i = 0; i < 25; ++i) {
            System.out.println("-----------------");
            Request request = makeRequest(String.format("%03d", i));
            firstHandler.handleRequest(request);
        }
    }

    private static List> makeHanlders() {
        List> handlers = new ArrayList<>();
        for (int i = 0; i < 20; ++i) {
            String request = String.format("%03d", i);
            handlers.add(makeHandler("handler" + request, makeRequest(request)));
        }
        return handlers;
    }

    private static Request makeRequest(String request) {
        return new Request(request) {
            @Override
            public boolean isSame(Request request) {
                return this.getRequest().equals(request.getRequest());
            }
        };
    }

    private static Handler makeHandler(final String handlerName, Request request) {
        return new Handler(request) {
            @Override
            protected void handle(Request request) {
                System.out.println(String.format("%s deal with request: %s", handlerName, request));
            }
        };
    }

    // 抽象消息
    static abstract class Request {
        ...
        ...
    }

    // 抽象处理者
    static abstract class Handler {
        ...
        ...
        private void setNextHandler(Handler handler) {
            this.mNextHandler = handler;
        }
        ...
        ...
        public static class Builder {
            private Handler mFirst;
            private Handler mLast;

            public Builder addHandler(Handler handler) {
                do {
                    if (this.mFirst == null) {
                        this.mFirst = this.mLast = handler;
                        break;
                    }
                    this.mLast.setNextHandler(handler);
                    this.mLast = handler;

                } while (false);
                return this;
            }

            public Handler build() {
                return this.mFirst;
            }
        }
    }
}

因为 建造者模式 要构建的是节点处理者,因此我们把Builder作为Handler的静态内部类,并且因为客户端无需进行链式组装,因此我们把链式组装方法setNextHandler设置为private,使Handler更加高内聚。

运行结果如下:

-----------------
handler000 deal with request: 000
-----------------
handler001 deal with request: 001
-----------------
handler002 deal with request: 002
-----------------
handler003 deal with request: 003
-----------------
handler004 deal with request: 004
-----------------
handler005 deal with request: 005
-----------------
handler006 deal with request: 006
-----------------
handler007 deal with request: 007
-----------------
handler008 deal with request: 008
-----------------
handler009 deal with request: 009
-----------------
handler010 deal with request: 010
-----------------
handler011 deal with request: 011
-----------------
handler012 deal with request: 012
-----------------
handler013 deal with request: 013
-----------------
handler014 deal with request: 014
-----------------
handler015 deal with request: 015
-----------------
handler016 deal with request: 016
-----------------
handler017 deal with request: 017
-----------------
handler018 deal with request: 018
-----------------
handler019 deal with request: 019
-----------------
No Handlers can handle this request: 020
-----------------
No Handlers can handle this request: 021
-----------------
No Handlers can handle this request: 022
-----------------
No Handlers can handle this request: 023
-----------------
No Handlers can handle this request: 024

举个例子

例子:小明是一个初级软件开发工程师,假设现在公司有几个需求需要开发,这些需求有些比较容易,有些比较困难。开发团队中有初级工程师,中级工程师,高级工程师和资深工程师,按需求难度进行划分,初级工程师能解决就交由初级工程师,否则将需求转交到更高一级工程师,直到资深工程师。如果资深工程师都无法解决这个需求,则要求产品更改需求。

分析:以上例子是一个典型的 责任链模式 需求,工程师对应节点处理者,需求对应请求。利用 责任链模式,只需将需求一个一个交由初级工程师(小明),需求就会自动地传递给具备相应能力进行开发的工程师手中,或者需求无法解决,则交由产品更改。

具体代码如下:

class Client {
    public static void main(String[] args) {
        Engineer xiaoming = new Engineer.Builder()
            .addEngineer(new JuniorEngineer())
            .addEngineer(new MidEngineer())
            .addEngineer(new SeniorEngineer())
            .addEngineer(new ProfessionalEngineer())
            .build();
        IProject easyProject = new EasyProject();
        IProject normalProject = new NormalProject();
        IProject hardProject = new HardProject();
        IProject tooHardProject = new TooHardProject();
        IProject beyondProject = new BeyondProject();

        if(!xiaoming.doWork(easyProject)){
            System.out.println("tell Product Manager: easy project can not complete");
        }
        if(!xiaoming.doWork(normalProject)){
            System.out.println("tell Product Manager: normal project can not complete");
        }
        if(!xiaoming.doWork(hardProject)){
            System.out.println("tell Product Manager: hard project can not complete");
        }
        if(!xiaoming.doWork(tooHardProject)){
            System.out.println("tell Product Manager: too hard project can not complete");
        }
        if(!xiaoming.doWork(beyondProject)){
            System.out.println("tell Product Manager: beyond project can not complete: "+beyondProject.difficulty());
        }
    }

    interface IProject {
        static int EASY = 0;
        static int NORMAL = 1;
        static int HARD = 2;
        static int TOO_HARD = 3;
        static int BEYOND = 4;

        // 项目难度
        int difficulty();
    }

    static class EasyProject implements IProject{

        @Override
        public int difficulty() {
            return IProject.EASY;
        }
    }
    static class NormalProject implements IProject{

        @Override
        public int difficulty() {
            return IProject.NORMAL;
        }
    }
    static class HardProject implements IProject{

        @Override
        public int difficulty() {
            return IProject.HARD;
        }
    }
    static class TooHardProject implements IProject{

        @Override
        public int difficulty() {
            return IProject.TOO_HARD;
        }
    }

    static class BeyondProject implements IProject{

        @Override
        public int difficulty() {
            return IProject.BEYOND;
        }
    }

    static abstract class Engineer {
        private Engineer mSuccessor;

        public final boolean doWork(IProject project) {
            boolean bRet = false;
            do {
                if (this.filterProject(project)) {
                    bRet = this.writeCode(project);
                    break;
                }
                if (this.mSuccessor != null) {
                    bRet = this.mSuccessor.doWork(project);
                    break;
                }
            } while (false);
            return bRet;
        }

        protected abstract boolean filterProject(IProject project);

        protected abstract boolean writeCode(IProject project);

        public static class Builder {
            private Engineer mFirst;
            private Engineer mLast;

            public Builder addEngineer(Engineer engineer) {
                if (this.mFirst == null) {
                    this.mFirst = this.mLast = engineer;
                } else {
                    this.mLast.mSuccessor = engineer;
                    this.mLast = engineer;
                }
                return this;
            }

            public Engineer build() {
                return this.mFirst;
            }
        }
    }

    // 初级工程师
    static class JuniorEngineer extends Engineer {

        @Override
        protected boolean filterProject(IProject project) {
            return project.difficulty() <= IProject.EASY;
        }

        @Override
        protected boolean writeCode(IProject project) {
            System.out.println("Junior engineer completes project: " + project.difficulty());
            return true;
        }
    }

    // 中级工程师
    static class MidEngineer extends Engineer {

        @Override
        protected boolean filterProject(IProject project) {
            return project.difficulty() <= IProject.NORMAL;
        }

        @Override
        protected boolean writeCode(IProject project) {
            System.out.println("Middle level engineer completes project: " + project.difficulty());
            return true;
        }
    }

    // 高级工程师
    static class SeniorEngineer extends Engineer {

        @Override
        protected boolean filterProject(IProject project) {
            return project.difficulty() <= IProject.HARD;
        }

        @Override
        protected boolean writeCode(IProject project) {
            System.out.println("Senior engineer completes project: " + project.difficulty());
            return true;
        }
    }

    // 资深工程师
    static class ProfessionalEngineer extends Engineer {

        @Override
        protected boolean filterProject(IProject project) {
            return project.difficulty() <= IProject.TOO_HARD;
        }

        @Override
        protected boolean writeCode(IProject project) {
            System.out.println("Professional engineer completes project: " + project.difficulty());
            return true;
        }
    }
}

结果如下:

Junior engineer completes project: 0
Middle level engineer completes project: 1
Senior engineer completes project: 2
Professional engineer completes project: 3
tell Product Manager: beyond project can not complete: 4

你可能感兴趣的:(责任链模式)