责任链模式——ChainOfResponsibility

案例展示——ChainOfResponsibility怎么用?

 考虑这样一个场景:现有一家工厂(大型综合一体化工厂),从原料生产到成品出产都由这家工厂独立完成。为了便于管理与提高效率,只能明确,工厂领导层决定将工厂一分为三:原料厂负责原料的生产和购买,零件制造厂负责零部件的制造,装配厂负责装配出厂。同时为了便于监管,督促各大工厂之间保质保量的完成任务,领导层委派很多监察者去各大工厂监察,每个监察者都有自己特定监察的工厂:原料厂监察者负责监察原料厂,零件制造厂监察者负责监察零件制造厂,装配厂监察者负责监察装配厂,每个人都各司其职。下面是类图设计:

image

分析上面的类图如下:

  • ISupervisor:监察者接口,可以获得监察者的监察请求和身份

  • Supervisor:具体的监察者,实现了ISupervisor接口

  • IHandler:有处理权的抽象人员接口

  • MaterialFactory,ProduceFactory,AssembleFactory:实现IHandler接口,具体的处理者

具体的代码实现如下:

//监察者接口
public interface ISupervisor {

    //获得生产阶段
    public int getStage();

    //获得监察请求
    public String getRequest();
}

//监察者
public class Supervisor implements ISupervisor {

    /**
     * 表示监察者身份
     * 1. 原料厂巡查
     * 2. 零件制造厂巡查
     * 3. 装配厂巡查
     */
    private int stage = 0;

    //监察请求
    private String request = "";

    //构造函数传递请求
    public Supervisor(int stage, String request) {
        this.stage = stage;
        this.request = request;
    }

    public int getStage() {
        return this.stage;
    }

    public String getRequest() {
        return this.request;
    }
}

//抽象处理者
public interface IHandler {

    //监察者要来巡查,处理请求
    public void HandlerMessage(ISupervisor supervisor);

}

//原料厂
public class MaterialFactory implements IHandler{
    //监察者要求巡查原料厂
    public void HandlerMessage(ISupervisor supervisor) {
        System.out.println("原料厂监察者巡查:" + supervisor.getRequest());
        System.out.println("原料厂回复:保质保量!");
    }
}

//零件制造厂
public class ProduceFactory implements IHandler {
    //监察者要求巡查零件制造厂
    public void HandlerMessage(ISupervisor supervisor) {
        System.out.println("零件制造厂监察者巡查:" + supervisor.getRequest());
        System.out.println("制造厂回复:做工精良!");
    }
}

//装配厂
public class AssembleFactory implements IHandler {
    //监察者要求巡查装配厂
    public void HandlerMessage(ISupervisor supervisor) {
        System.out.println("装配厂监察者巡查:" + supervisor.getRequest());
        System.out.println("装配厂回复:效率第一!");
    }
}



//在一个场景类中运行代码
public class Client {

    public static void main(String[] args) {
        //产生多个监察者(身份随机)
        Random random = new Random();
        ArrayList<ISupervisor> list = new ArrayList<ISupervisor>();
        for (int i = 0; i < 5; i++) {
            list.add(new Supervisor(random.nextInt(4), "我将来巡查,做好准备!"));
        }

        //定义三个请示对象
        Handler material = new MaterialFactory();
        Handler producer = new ProduceFactory();
        Handler assemble = new AssembleFactory();

        //设置顺序
        material.setNextHandler(producer);
        producer.setNextHandler(assemble);
        for (ISupervisor supervisor : list) {
            material.HandlerMessage(supervisor);
        }
    }
}

//结果如下:

===========去原料厂巡查==========
原料厂监察者巡查:我将来巡查,做好准备!
原料厂回复:保质保量!
===========去零件制造厂巡查==========
零件制造厂监察者巡查:我将来巡查,做好准备!
制造厂回复:做工精良!
===========去装配厂巡查==========
装配厂监察者巡查:我将来巡查,做好准备!
装配厂回复:效率第一!

 观察了上面的设计与代码实现,虽然得到了我们想要的结果,但是却有几个地方需要改进:

  • 高层模块对低层模块依赖太深,不利于扩展:对于监察者的身份与检查请求,应该由具体的处理类去得到,而不应该由高层模块去逻辑判断指定

  • 耦合过重:我们需要根据监察者的身份来决定使用IHandler的哪个实现类,但是假如IHandler的实现类继续扩展,我们将不得不去修改高层模块(Client类)

 所以正确的处理请求应该是这样的,首先,每个工厂应该提前知道监察者的身份,判断自己能否接受监察,如果不能将其传递给下一个工厂。下面是类图设计:

image

分析上面的类图如下:

  • Handler:使用了模板方法模式,在模板方法中判断监察者的身份和自己能否做出处理,如果能处理则做出反馈,如果不能处理就传递给下一个环节,直到环节结束。基本方法response需要每个实现类去实现,每个实现类只实现两个职责:1. 定义自己能够接纳的监察者身份;2. 对请求做出回应

下面是具体的代码实现:

//监察者接口
public interface ISupervisor {

    //获得生产阶段
    public int getStage();

    //获得监察请求
    public String getRequest();
}

//监察者
public class Supervisor implements ISupervisor{
    /**
     * 表示监察者身份
     * 1. 原料厂巡查
     * 2. 零件制造厂巡查
     * 3. 装配厂巡查
     */
    private int stage = 0;

    //监察者请求
    private String request = "";

    //构造函数传递请求
    public Supervisor(int stage, String request) {
        this.stage = stage;

        switch (this.stage) {
            case 1:
                this.request = "原料厂监察者巡查:" + request;
                break;
            case 2:
                this.request = "零件制造厂监察者巡查:" + request;
                break;
            case 3:
                this.request = "装配厂监察者巡查:" + request;
        }
    }

    public int getStage() {
        return this.stage;
    }

    public String getRequest() {
        return this.request;
    }
}

//抽象处理类
public abstract class Handler {

    public final static int MATERIAL_STAGE = 1;
    public final static int PRODUCE_STAGE = 2;
    public final static int ASSEMBLE_STAGE = 3;

    //监察者身份:巡查对应身份的工厂
    private int stage = 0;

    //责任传递:不是对应的巡查请求向下传递
    private Handler nextHandler;

    //自己能接受谁的巡查
    public Handler(int stage) {
        this.stage = stage;
    }

    //监察者要来巡查,需要处理请求
    public final void HandlerMessage(ISupervisor supervisor) {
        if (supervisor.getStage() == this.stage) {
            this.response(supervisor);
        } else {
            if (this.nextHandler != null) { //后续环节
                this.nextHandler.HandlerMessage(supervisor);
            } else { //没有后续处理人
                System.out.println("=======没有可巡查的工厂了======");
            }
        }
    }
    /**
     * 不是对应的处理请求,传递给下一个
     */
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    //进行回应
    protected abstract void response(ISupervisor supervisor);
}

//原料厂
public class MaterialFactory extends Handler {
    //处理身份是原料厂监察者的请求
    public MaterialFactory() {
        super(Handler.MATERIAL_STAGE);
    }

    /**
     * 巡查原料厂
     */
    protected void response(ISupervisor supervisor) {
        System.out.println("===========去原料厂巡查==========");
        System.out.println(supervisor.getRequest());
        System.out.println("原料厂回复:保质保量!");
    }
}

//零件制造厂
public class ProduceFactory extends Handler {
    //处理身份是零件制造厂监察者的请求
    public ProduceFactory() {
        super(Handler.PRODUCE_STAGE);
    }

    /**
     * 巡查零件制造厂
     */
    protected void response(ISupervisor supervisor) {
        System.out.println("===========去零件制造厂巡查==========");
        System.out.println(supervisor.getRequest());
        System.out.println("制造厂回复:做工精良!");
    }
}

//装配厂
public class AssembleFactory extends Handler {
    //处理身份是装配厂监察者的请求
    public AssembleFactory() {
        super(Handler.ASSEMBLE_STAGE);
    }

    /**
     * 巡查装配厂
     */
    protected void response(ISupervisor supervisor) {
        System.out.println("===========去装配厂巡查==========");
        System.out.println(supervisor.getRequest());
        System.out.println("装配厂回复:效率第一!");
    }
}


//在一个场景类中运行代码
public class Client {

    public static void main(String[] args) {
        //产生多个监察者(身份随机)
        Random random = new Random();
        ArrayList<ISupervisor> list = new ArrayList<ISupervisor>();
        for (int i = 0; i < 5; i++) {
            list.add(new Supervisor(random.nextInt(4), "我将来巡查,做好准备!"));
        }

        //定义三个请示对象
        Handler material = new MaterialFactory();
        Handler producer = new ProduceFactory();
        Handler assemble = new AssembleFactory();

        //设置顺序
        material.setNextHandler(producer);
        producer.setNextHandler(assemble);
        for (ISupervisor supervisor : list) {
            material.HandlerMessage(supervisor);
        }
    }
}

//结果如下:
===========去原料厂巡查==========
原料厂监察者巡查:我将来巡查,做好准备!
原料厂回复:保质保量!
===========去零件制造厂巡查==========
零件制造厂监察者巡查:我将来巡查,做好准备!
制造厂回复:做工精良!
===========去装配厂巡查==========
装配厂监察者巡查:我将来巡查,做好准备!
装配厂回复:效率第一!

 我们发现结果是正确的,高层模块Client不用去主动判断监察者的身份,而是由每个处理者自己去获取,而且Handler可以自己扩展,只要设置好传递链就可以了,监察者的请求会在这条链上进行传递,会有对应的处理者去处理请求。这就是责任链模式

深入分析——ChainOfResponsibility是什么?

ChainOfResponsibility的定义

定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,直到有对象处理它为止。下面是通用类图:

image

责任链模式的核心: 由一条链去处理相似的请求,并在链中决定由谁来处理这个请求,同时返回相应的结果。

下面是通用代码:

//抽象处理者
public abstract class Handler {
    private Handler nextHandler;
    //每个处理者需要对请求作出处理
    public final Response handlerMessage(Request request) {
        Response response = null;
        //判断是否是自己的处理级别
        if (this.getHandlerLevel().equals(request.getRequestLevel())) {
            response = this.echo(request);
        } else { //不属于自己的处理级别
            //判断是否有下一个处理者
            if (this.nextHandler != null) {
                response = this.nextHandler.handlerMessage(request);
            } else {
                //没有适当处理者
            }
        }
        return response;
    }

    //设置下一个处理者
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    //每个处理者对应的处理级别
    protected abstract Level  getHandlerLevel();

    //处理者实现自己的处理任务
    protected abstract Response echo(Request request);
}

//具体处理者
public class ConcreateHandler1 extends Handler {
    //处理逻辑
    protected Level getHandlerLevel() {
        return null;
    }

    //设置处理级别
    protected Response echo(Request request) {
        return null;
    }
}
public class ConcreateHandler2 extends Handler {
    //处理逻辑
    protected Level getHandlerLevel() {
        return null;
    }

    //设置处理级别
    protected Response echo(Request request) {
        return null;
    }
}
public class ConcreateHandler3 extends Handler {
    //处理逻辑
    protected Level getHandlerLevel() {
        return null;
    }

    //设置处理级别
    protected Response echo(Request request) {
        return null;
    }
}

//框架代码
public class Level {
    //定义请求和处理等级
}
public class Request {
    //请求的等级
    public Level getRequestLevel() {
        return null;
    }
}
public class Response {
    //处理者返回数据
}


//场景类
public class Client {
    public static void main(String[] args) {
        //声明所有的处理者
        Handler handler1 = new ConcreateHandler1();
        Handler handler2 = new ConcreateHandler2();
        Handler handler3 = new ConcreateHandler3();

        //设置处理顺序
        handler1.setNextHandler(handler2);
        handler2.setNextHandler(handler3);

        //提交请求,返回结果
        Response response = handler1.handlerMessage(new Request());
    }
}
ChainOfResponsibility的优点
  • 将请求与处理分开,请求者可以不用知道是谁处理的请求,处理者可以不用知道请求者的详细细节

  • 屏蔽了请求的处理过程,可以不用去操心我的请求应该发给哪个处理者,只要把它扔给第一个处理者,让它自己去判断和传递

参考

《设计模式之禅》

猜你喜欢

转载自blog.csdn.net/king123456man/article/details/82994318