责任链模式——ChainOfResponsibility
案例展示——ChainOfResponsibility怎么用?
考虑这样一个场景:现有一家工厂(大型综合一体化工厂),从原料生产到成品出产都由这家工厂独立完成。为了便于管理与提高效率,只能明确,工厂领导层决定将工厂一分为三:原料厂负责原料的生产和购买,零件制造厂负责零部件的制造,装配厂负责装配出厂。同时为了便于监管,督促各大工厂之间保质保量的完成任务,领导层委派很多监察者去各大工厂监察,每个监察者都有自己特定监察的工厂:原料厂监察者负责监察原料厂,零件制造厂监察者负责监察零件制造厂,装配厂监察者负责监察装配厂,每个人都各司其职。下面是类图设计:
分析上面的类图如下:
-
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类)
所以正确的处理请求应该是这样的,首先,每个工厂应该提前知道监察者的身份,判断自己能否接受监察,如果不能将其传递给下一个工厂。下面是类图设计:
分析上面的类图如下:
- 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的定义
定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,直到有对象处理它为止。下面是通用类图:
责任链模式的核心: 由一条链去处理相似的请求,并在链中决定由谁来处理这个请求,同时返回相应的结果。
下面是通用代码:
//抽象处理者
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的优点
-
将请求与处理分开,请求者可以不用知道是谁处理的请求,处理者可以不用知道请求者的详细细节
-
屏蔽了请求的处理过程,可以不用去操心我的请求应该发给哪个处理者,只要把它扔给第一个处理者,让它自己去判断和传递
参考
《设计模式之禅》