责任链模式属于行为类模式,其意图是将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
责任链的核心在“链”上,“链”是由多个处理者组成的,“链”上的处理者负责处理请求,客户只需将请求发送到“链”上即可,无需关心请求的处理细节和请求的传递方向。这样请求的发送者和请求的处理者实现了解耦。
示例
定义一个业务场景,DNS协议“规定”每个区域的DNS服务器(Local DNS)只保留自己区域的域名解析,对于不能解析的域名,则提交上级域名解析器解析,最终由一台位于美国洛杉矶的顶级域名服务器进行解析,返回结果。三个DNS服务器分别为:上海DNS服务器(区域服务器)、中国顶级DNS服务器(父服务器)、全球顶级DNS服务器。DNS解析示意图如下:
示例类图如下:
/**
* 解析记录POJO
* @author wei.jiang
* @since 2016-09-21
*/
public class Recorder {
/**域名**/
private String domain;
/**IP**/
private String ip;
/**属主**/
private String owner;
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
@Override
public String toString() {
return domain+"由"+owner+", 解析后的IP为"+ip;
}
}
/**
* DnsServer抽象类
* @author wei.jiang
* @since 2016-09-21
*/
public abstract class DnsServer {
//上级DnsServer
private DnsServer upperServer;
/**
* 解析域名
* @param domain
* @return
*/
public final Recorder resolve(String domain){
Recorder recorder = null;
if(this.isLocal(domain)){//本级能解析的域名
recorder = echo(domain);
}else{//本级不能解析的域名,提交上级解析
recorder = this.upperServer.resolve(domain);
}
return recorder;
}
/**
* 指向上级DNS
* @param upperServer
*/
public void setUpperServer(DnsServer upperServer){
this.upperServer = upperServer;
}
//本级能否解析该域名
protected abstract boolean isLocal(String domain);
/**
* 每个DNS服务器必须实现解析任务
* @param domain
* @return
*/
protected Recorder echo(String domain){
Recorder recorder = new Recorder();
recorder.setDomain(domain);
recorder.setIp(getIp());
return recorder;
}
/**
* 随机生成一个IP地址
* @return
*/
private String getIp(){
Random random = new Random();
return random.nextInt(255)+"."+random.nextInt(255)
+"."+random.nextInt(255)+"."+random.nextInt(255);
}
}
/**
* 上海DnsServer实现类
* @author wei.jiang
* @since 2016-09-21
*/
public class SHDnsServer extends DnsServer {
/**
* 定义上海DNS能够处理的级别
*/
@Override
protected boolean isLocal(String domain) {
return domain.endsWith(".sh.cn");
}
protected Recorder echo(String domain){
Recorder recorder = super.echo(domain);
recorder.setOwner("上海DNS服务器解析");
return recorder;
}
}
/**
* 中国顶级DnsServer实现类
* @author wei.jiang
* @since 2016-09-21
*/
public class ChinaDnsServer extends DnsServer{
/**
* 定义中国顶级DNS能够处理的级别
*/
@Override
protected boolean isLocal(String domain) {
return domain.endsWith(".cn");
}
protected Recorder echo(String domain){
Recorder recorder = super.echo(domain);
recorder.setOwner("中国DNS服务器解析");
return recorder;
}
}
/**
* 全球顶级DnsServer实现类
* @author wei.jiang
* @since 2016-09-21
*/
public class TopDnsServer extends DnsServer {
@Override
protected boolean isLocal(String domain) {
return true;
}
protected Recorder echo(String domain){
Recorder recorder = super.echo(domain);
recorder.setOwner("顶级DNS服务器解析");
return recorder;
}
}
/**
* 场景类
* @author wei.jiang
* @since 2016-09-21
*/
public class Client {
public static void main(String[] args) throws IOException {
//上海域名服务器
DnsServer sHDnsServer = new SHDnsServer();
//中国顶级域名服务器
DnsServer chinaDnsServer = new ChinaDnsServer();
//全球顶级域名服务器
DnsServer topDnsServer = new TopDnsServer();
//定义查询路径
sHDnsServer.setUpperServer(chinaDnsServer);
chinaDnsServer.setUpperServer(topDnsServer);
System.out.println("-------域名解析模拟器------");
while(true){
System.out.println("请输入域名(输入N退出):");
String domain = (new BufferedReader(new InputStreamReader(System.in))).readLine();
if(domain != null && !"".equals(domain)){
if(domain.equalsIgnoreCase("N")){
return;
}
Recorder recorder = sHDnsServer.resolve(domain);
System.out.println(recorder.toString());
}else{
System.out.println("请输入域名:(输入N退出):");
}
}
}
}
输出结果:
-------域名解析模拟器------
请输入域名(输入N退出):
www.baidu.sh.cn
www.baidu.sh.cn由上海DNS服务器解析, 解析后的IP为234.135.13.216
请输入域名(输入N退出):
www.baidu.cn
www.baidu.cn由中国DNS服务器解析, 解析后的IP为110.237.58.78
请输入域名(输入N退出):
www.baidu.com
www.baidu.com由顶级DNS服务器解析, 解析后的IP为131.55.162.121
请输入域名(输入N退出):
N
责任链模式通用类图
Handler:抽象处理者,需实现三个职责
- 定义一个请求的处理方法
- 定义一个链路的编排方法
- 定义自己能够处理的级别和具体的处理任务
抽象处理者通用代码:
/**
* 抽象处理者
* @author wei.jiang
* @since 2016-09-21
*/
public abstract class Handler {
private Handler nextHandler;
/**
* 处理请求
* @param request
* @return
*/
public final Response handleMessage(Request request){
Response response = null;
if(this){
}else{
}
}
}
ConcreteHandler:具体的处理者