Java 设计模式 -- 职责链模式
2016-05-20 21:44
399 查看
下面,将通过一个例子,对职责链模式进行介绍。
问题:设想,你有一个呼叫中心,员工分成三个层级,接线员,主管和经理。客户来电时会先分配给接线员,若接线员处理不了,就必须将来电往上转给主管,若主管无法处理,将来电往上转给经理。请设计这个问题的类和数据结构(为了方便,将呼叫者的问题分等级,分别为 S 级,由接线员处理,SS 级,由主管处理,SSS级,由经理处理)。
首先,分析一下这个问题,对于一次电话呼叫,肯定存在 呼叫人和被呼叫人,所以我们可能需要设计一个 Call 类来表示一个电话呼叫,一个 Caller 类用于封装呼叫人的属性,Employee 类用于表示接听人,因为员工分三种,所以我们需要将 Employee 定义为一个抽象类,用于封装员工的共同属性。既然各个类模型已经想好了,那么就要想想如何设计方法呢?也就是如何实现电话的传递呢?想想 Java 中是如何模仿指针效果的?下面来看看实现
以上为
以上是一个抽象类,定义了一个属性和两个方法,
以上实现表明,
这里如果经理也处理不了该通话,只能打印不能处理该问题,不能再往上传递,否则会报空指针错误。
下面来看看
在这里,我们有一个
其实,我们已经在很多地方见到过这种模式,比如说
再比如说
我所理解的职责链模式就是如此,如果有什么错误的地方,希望予以指正,互相学习。
问题:设想,你有一个呼叫中心,员工分成三个层级,接线员,主管和经理。客户来电时会先分配给接线员,若接线员处理不了,就必须将来电往上转给主管,若主管无法处理,将来电往上转给经理。请设计这个问题的类和数据结构(为了方便,将呼叫者的问题分等级,分别为 S 级,由接线员处理,SS 级,由主管处理,SSS级,由经理处理)。
首先,分析一下这个问题,对于一次电话呼叫,肯定存在 呼叫人和被呼叫人,所以我们可能需要设计一个 Call 类来表示一个电话呼叫,一个 Caller 类用于封装呼叫人的属性,Employee 类用于表示接听人,因为员工分三种,所以我们需要将 Employee 定义为一个抽象类,用于封装员工的共同属性。既然各个类模型已经想好了,那么就要想想如何设计方法呢?也就是如何实现电话的传递呢?想想 Java 中是如何模仿指针效果的?下面来看看实现
public class Caller { private String mName; private String mRank; public Caller(String rank) { this.mRank = rank; } public String getName() { return mName; } public void setName(String name) { this.mName = name; } public String getRank() { return mRank; } public void setRank(String rank) { mRank = rank; } public void disconnect() { System.out.println("Caller : disconnect"); } }
以上为
Caller方法,只有一个带问题等级参数的构造函数,用于表示呼叫者必须首先声明自己问题的等级。还有一个
disconnect()方法,当呼叫者问题被处理完毕后调用,表示挂掉电话。
public abstract class Employee { protected Employee mBoss; public abstract void setBoss(Employee boss); public abstract void handleCall(Call call); }
以上是一个抽象类,定义了一个属性和两个方法,
setBoss()用于设置当前员工的顶头上司,
handleCall()方法在员工接听电话时调用。下面来看看 接线员类的实现
public class Respondent extends Employee { @Override public void handleCall(Call call) { if (call.getCaller().getRank().equals("S")) { System.out.println("Respondent : handle this call"); call.getCaller().disconnect(); } else { mBoss.handleCall(call); } } @Override public void setBoss(Employee boss) { mBoss = boss; } }
以上实现表明,
setBoss()方法必须在
handleCall()方法之前调用,否则会报空指针错误,因为在
handleCall()方法逻辑中,我们设置了,如果该员工能处理指定信息,则进行处理,处理完之后呼叫者挂断电话。如果不能处理,就将该呼叫传递给自己的顶头上司,交给他去处理。需要注意的是对于
Manager类的实现,由于它已经没有上司,所以在
handleCall()方法中做特殊处理,如下所示
@Override public void handleCall(Call call) { if (call.getCaller().getRank().equals("SSS")) { System.out.println("Manager : handle this call"); call.getCaller().disconnect(); } else { System.out.println("We can not handle this call"); } }
这里如果经理也处理不了该通话,只能打印不能处理该问题,不能再往上传递,否则会报空指针错误。
下面来看看
Call类是如何实现的
public class Call { private Caller mCaller; private Employee mEmployee; public Call(Caller caller) { this.mCaller = caller; } public Caller getCaller() { return mCaller; } public void handle() { mEmployee.handleCall(this); } public void setRespondent(Employee respondent) { mEmployee = respondent; } }
在这里,我们有一个
setRespondent()方法,这里设置的员工是接线员,因为只有这样才可以确保如果该通话无法被处理向上传递。看到这里,感觉这种模式就像踢皮球一样,你踢给我,我踢给你,当然也可以这么形容,这种模式的实现思想和指针类似。
其实,我们已经在很多地方见到过这种模式,比如说
Java的异常机制,如果一个地方抛出了异常,会首先寻找距离最近的
catch语句,如果可以处理,就处理,不可以处理,就再往上抛,直到可以被处理为止。
再比如说
Android当中的触摸事件,也是从容器中一级一级向下传,直到传到最底层的 View 视图,当然传到其中的任何一个容器的时候,都可以截断这种传递。
我所理解的职责链模式就是如此,如果有什么错误的地方,希望予以指正,互相学习。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序