欢迎大家提出意见,一起讨论!
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
例子代码:(编译工具:Eclipse)
http://www.rayfile.com/zh-cn/files/2a49656e-91da-11e1-a750-0015c55db73d/
参考书籍: <<软件秘笈-----设计模式那点事>>
责任链模式(Chain of Responsibility Pattern),是一种对象的形为模式。在责任链模式中,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
客户端应用请求在这个链上传递,直到链上某一个对象决定处理此请求。
责任链模式涉及的角色如下。
(1)抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回下家的引用。这个角色通常由一个Java抽象类或Java接口实现。
(2)具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。
下面以学生请假的流程为例进行说明.
来一起分析学生请假的流程。
(1)小学生生病了,发出请假请求。
(2)请假请求首先发给班长,看看班长能否处理。如果班长能够处理,则由班长批准请假;否则,交给老师处理。
(3)老师接到学生请假请求,首先判断病情是否严重。如果是一般的小病,则老师批准请假;否则,交给校长处理。
(4)校长接到学生请假请求,核实属实,则给予请假批准。
在一般情况下是如何分析解决这样的问题的。如图14-2所示,为一般情况学生请假关系类图。
根据设计模式中的依赖倒置原则,即面向抽象编程,而不要而向实现编程,首先定义两个接口:学生请假接口IStudent和请求处理接口IHandler。
在学生请假接口中存在两个方法:分别为病情状态(这个用来标识由谁来处理)和请求消息。而IHandler请求处理接口很简单,就是接收学生请假请求进行处理。
为了更好地扩展我们再增加一不念旧恶请求的抽象处理者AbstractHandler,该抽象处理者实现IHandler接口,实现学生请求处理接口方法,
然后使用模板方法,由子类实现具体的处理过程。
班长、老师和校长都继承抽象处理者AbstractHandler。
责任链的实现关键在于消息在链条上的传递,需要做到以下几点内容:
(1)在处理者中要含有链条中下一节点的引用。在抽象处理者AbstractHandler中增加一个IHandler类型的私有属性,用于保存对下家处理者的引用。
(2)每一个消息处理者都应该含有一个处理消息的标记位,用来标识当前处理者含有处理消息的级别。
(3)最后一点,也是最重要的一点就是,处理消息的方法需要链条化。
根据上面的内容修改完善静态类图,如图
下面我们就开始实现吧!
一.学生请假实现
1、学生接口------IStudent
首先,我们创建学生请求接口IStudent,该接口类中含有两个接口方法:一个是获得学生病情状态,另一个是获取学生请假内容。
/**
* 学生接口
*
* @author
*
*/
public interface IStudent {
/**
* 获得学生病情状态
*
* 0:小事(班长就可以处理)
*
* 1:班长处理不了 老师能处理的事
*
* 2:老师处理不了 校长能处理的事
*
*
*/
public int getState();
/**
* 获得学生请假消息
*
* @return
*/
public String getRequestMessage();
}
2、学生的实现.
在学生请假实现类中,定义了两个私有属性:病情状态和请假内容,通过构造方法传入。
/**
* 学生实现类
*
* @author
*
*/
public class Student implements IStudent {
// 病情的大小状态
private int state = -1;
// 请假消息
private final String message;
public Student(int state, String message) {
this.state = state;
this.message = message;
}
/**
* 获得学生请假状态
*
* 0:小事(班长就可以处理)
*
* 1:班长处理不了 老师能处理的事
*
* 2:老师处理不了 校长能处理的事
*
*
*/
public int getState() {
return this.state;
}
/**
* 获得学生请假消息
*
* @return
*/
public String getRequestMessage() {
return this.message;
}
}
二.创建抽象请假消息处理者
1、抽象处理者接口----IHandler
/**
* 抽象处理者接口
*
* @author
*
*/
public interface IHandler {
// 处理请求
public void handleRequest(IStudent student);
// 设置下一个处理者
public void setHandler(IHandler handler);
}
2、抽象者处理----AbstractHandler
它的存在是将处理学生的请求过程抽象化,而对学生请假请求的处理措施则由具体的子类来实现。
/**
* 抽象处理者
*
* @author
*
*/
public abstract class AbstractHandler implements IHandler {
// 下一个处理者
private IHandler handler;
// 请假级别
private int state = -1;
// 构造方法 设置级别
public AbstractHandler(int state) {
this.state = state;
}
// 处理请求 交由子类负责进行具体的处理
public abstract void process(IStudent student);
// 处理请求
public void handleRequest(IStudent student) {
// 如果学生对象存在
if (student != null) {
if (this.state == student.getState()) {
// 如果请假级别和当前一致 则当前对象进行处理
this.process(student);
} else {
if (this.handler != null) {
System.out.println("请求上级领导批复!");
// 如果当前对象处理不了 则交给下一个处理者进行处理
this.handler.handleRequest(student);
}
}
}
}
// 设置下一个处理者
public void setHandler(IHandler handler) {
this.handler = handler;
}
}
三.请假处理者具体实现
1、班长---SquadLeaderHandler
需要实现处理方法process
/**
* 班长处理者
*
* @author
*
*/
public class SquadLeaderHandler extends AbstractHandler {
public SquadLeaderHandler() {
super(0);
}
// 子类具体处理请求
@Override
public void process(IStudent student) {
System.out.println("班长 批复:" + student.getRequestMessage());
}
}
2、老师----TeacherHandler
/**
* 老师处理者
*
* @author
*
*/
public class TeacherHandler extends AbstractHandler {
public TeacherHandler() {
super(1);
}
// 子类具体处理请求
@Override
public void process(IStudent student) {
System.out.println("老师 批复:" + student.getRequestMessage());
}
}
3、校长----SchoolMasterHandler
/**
* 校长处理者
*
* @author
*
*/
public class SchoolMasterHandler extends AbstractHandler {
public SchoolMasterHandler() {
super(2);
}
// 子类具体处理请求
@Override
public void process(IStudent student) {
System.out.println("校长 批复:" + student.getRequestMessage());
}
}
三.客户端测试
创建Client客户端应用程序,首先需要创建三个请求处理者:班长、老师和校长;
然后处理者根据学生病情的状态,对学生的请假分别做出不同的处理。
为了符“开-闭”原则(即做到扩展开放,对修改关闭的),这里处理者是变化的部分,可能会增加,我们需要抽象和封装。
于是采用外观模式,增加一个外观,让外观与处理者对象打交道,而客户端应用程序调用外观处理学生请假请求。
/**
* 设置责任链关联
*
* @author
*
*/
public class ProcessHandler {
// 班长处理者
private final IHandler sqmshandler;
// 老师处理者
private final IHandler techhandler;
// 校长处理者
private final IHandler scmshandler;
// 单例模式
private static ProcessHandler processHandler = new ProcessHandler();
/**
* 构造方法建立请假处理责任链
*/
private ProcessHandler() {
// 创建处理对象
// 班长
this.sqmshandler = new SquadLeaderHandler();
// 老师
this.techhandler = new TeacherHandler();
// 校长
this.scmshandler = new SchoolMasterHandler();
/**
* 建立责任链
*/
// 设置班长的下一个处理者:老师
this.sqmshandler.setHandler(this.techhandler);
// 设置老师的下一个处理者:校长
this.techhandler.setHandler(this.scmshandler);
}
/**
* 获得单例对象实例
*
* @return
*/
public static ProcessHandler getInstance() {
return processHandler;
}
/**
* 发送请假请求
*
* @param message
*/
public void sendMessage(IStudent student) {
// 发送给第一个处理者:班长 处理
this.sqmshandler.handleRequest(student);
}
}
客户端如下:
/**
* 主应用程序
*
* @author
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// 获得外观对象
ProcessHandler processHandler = ProcessHandler.getInstance();
// 创建随机数对象 用来随机产生学生对象
Random random = new Random();
for (int i = 0; i < 3; i++) {
// 获得随机数
int radom = random.nextInt(3);
IStudent student = new Student(radom, "学生" + i + "生病了,要请假!");
System.out.println("#################################");
// 处理消息
processHandler.sendMessage(student);
System.out.println("#################################\n");
}
}
}
================================================================================================
总结:
一、设计原则
1、"开-闭"原则
它是设计模式的核心原则,在每一个设计模式中都有体现,责任链中的"开-闭"原则体现在可以动态地扩展责任链当中的处理节点。
而无须改动客户端应用,程序结构更加清晰,同时也大大保证了系统运行的稳定性。
2、单一职责原则.
消息处理者只完成各自的本职工作,尽量做到功能单一,这为后期的测试维护工作带来方便,每一个类的功能单一,我们可以一定
定位问题所在,节省了找错时间。