"围观"设计模式(22)--行为型之职责链模式(Chain Of Responsibility Pattern)

Posted 低调的洋仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了"围观"设计模式(22)--行为型之职责链模式(Chain Of Responsibility Pattern)相关的知识,希望对你有一定的参考价值。

责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。----WIKIPEDIA


个人的理解

责任链模式用到了链表的数据结构,存在一定的次序性,A->B->C这样的一条链表,在责任链模式中,请求交给A进行处理,如果A处理不了交给B,B如果处理的了进行处理,否则交给C处理,模式的关键在于构建这样的一个链表,并且完成链表之间这些处理情况的切换,这一点在定义中应该是说可以把不能处理的命令对象传递给链中的下一个处理对象。这么看来的话,我们平时的分层结构是不是可以理解为非纯正的责任链模式呢?但是我们分层的结构中可能每一层都要完成一些自己应该做的事情,那么,这样的话并不是和责任链模式一致,因为在责任链中是将整个的‘责任’推给下一个节点,不过从某种意义上看的话是有点相似的,因为这也是我个人的理解和思考,读者有不同的意见可以评论。


案例解析


DNS递归查询模拟案例


DNS解析中,有两种方式,一种为递归的查询方式,另一种为迭代的查询方式,递归的查询方式是先访问本地的DNS服务器,本地的DNS服务器中没有,去询问根域名服务器,根域名服务器知道哪台服务器,然后就返回结果,如果不知道,就询问一级域名服务器,然后一级域名服务器询问二级等等直到找到为止,由根域名服务器交给本地域名服务器交给用户的应用。迭代的方式应该是本地域名服务器向根域名服务器询问,不知道的话,交给本地域名服务器一级域名服务器的地址,然后本地域名服务器再去询问一级域名服务器,这样不断的迭代的过程,最终本地域名服务器可以直接拿到想要的DNS域名的映射结果。


那么,我觉得递归的方式更像是职责链模式,因为对于用户这一端来说,本地域名服务器相当于我们的接口,具体的访问细节,作为用户而言,不需要知道的,那么本地域名服务器相当于我们这个实例中的进行一系列切换和请求的调度员,不同的实现之间通过不断的查询自身节点和切换下一个节点查询来实现最终结果的返回。类的结构图如下:


其中response方法为负责进行处理并返回结果的。下面列出主要的代码:

抽象类Handler:

public abstract class Handler {

	private Handler nextHandler;
	// key-->domain; value-->ip
	protected Map<String, String> domain = new HashMap<String, String>();
	
	public final String handlerMessage(String domain) {
		// 当前的节点存在该DNS的映射的话直接返回
		if(this.domain != null && this.domain.containsKey(domain))
			return this.domain.get(domain);
		// 切换到下一个节点处理
		else{
			return this.nextHandler.handlerMessage(domain);
		}
	}
	
	public void setNextHandler(Handler nextHandler) {
		this.nextHandler = nextHandler;
	}

	public void setDomain(Map<String, String> domain) {
		this.domain = domain;
	}
	
	// 返回的信息
	public abstract String response(String domain);
	
}
抽象处理类的作用是完成 请求的处理方法,还有设置下一个节点进行切换。


具体的实现类

public class LocalHandler extends Handler {

	public LocalHandler() {
		super();
		this.domain.put("www.baidu.com", "115.239.210.27");
	}

	@Override
	public String response(String domain) {
		return this.domain.get(domain);
	}

}

public class FirstHandler extends Handler {

	public FirstHandler() {
		super();
		this.domain.put("www.alibaba.com", "140.205.94.232");
	}
	
	@Override
	public String response(String domain) {
		return this.domain.get(domain);
	}

}

public class SecondHandler extends Handler {

	public SecondHandler() {
		super();
		this.domain.put("www.tecent.com", "183.60.38.45");
	}
	
	@Override
	public String response(String domain) {
		
		return this.domain.get(domain);
	}

}

测试类

public class MainTest {

	public static void main(String[] args) {
		Handler local = new LocalHandler();
		Handler first = new FirstHandler();
		Handler second = new SecondHandler();
		
		local.setNextHandler(first);
		first.setNextHandler(second);
		
		String ip = local.handlerMessage("www.alibaba.com");
		System.out.println(ip);
	}
}

基本模板

伪代码的形式进行展示。


请求处理角色Handler


public abstract class Handler {

	// 下一个节点
	private Handler nextHandler;
	
	public final Response handleMessage(Request requst) {
		Response response = null;
		// 判断是否是自己的处理级别
		if(this.getHandlerLevel().equals(requst.getRequestLevel())) {
			response = this.echo(requst);
		}else {
			if(this.nextHandler != null) {
				response = this.nextHandler.handleMessage(requst);
			}
			else{
				// 自行处理
			}
		}
		return response;
	}
	
	public void setNext(Handler handler) {
		this.nextHandler = handler;
	}
	
	// 处理的级别
	protected abstract Level getHandlerLevel();
	
	// 处理者实现的处理任务
	protected abstract Response echo(Request requst);
	
}
实现细节类
public class ConcreteHandler1 extends Handler {

	@Override
	protected Level getHandlerLevel() {
		return null;
	}

	@Override
	protected Response echo(Request requst) {
		return null;
	}

}

public class ConcreteHandler2 extends Handler {

	@Override
	protected Level getHandlerLevel() {
		return null;
	}

	@Override
	protected Response echo(Request requst) {
		return null;
	}

}

public class ConcreteHandler3 extends Handler {

	@Override
	protected Level getHandlerLevel() {
		return null;
	}

	@Override
	protected Response echo(Request requst) {
		return null;
	}

}

测试类


public class MainTest {

	public static void main(String[] args) {
		Handler handler1 = new ConcreteHandler1();
		Handler handler2 = new ConcreteHandler2();
		Handler handler3 = new ConcreteHandler3();
		
		handler1.setNext(handler2);
		handler2.setNext(handler3);
		
		Response response = handler1.handleMessage(new Request());
	}
}<span style="font-size:18px;"><strong><span style="font-size:12px;"></span></strong></span>


责任链的优点

请求和处理剥离开来,请求者不需要知道是谁处理的,而处理者也不用知道请求的全部信息。


责任链的缺点

1. 链表比较长的时候性能可能较低。

2. 链表比较长的时候调试和纠错比较复杂。


设计模式源代码下载

设计模式源代码下载地址


推荐阅读

"围观"设计模式(18)--行为型之模板方法模式(TemplateMethod Pattern)

"围观"设计模式(19)--行为型之观察者模式(Observer Pattern)

"围观"设计模式(20)--行为型之策略模式(Strategy Pattern)

"围观"设计模式(21)--行为型之状态模式(State Pattern)


以上是关于"围观"设计模式(22)--行为型之职责链模式(Chain Of Responsibility Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

"围观"设计模式(15)--结构型之桥梁模式(Bridge Pattern)

"围观"设计模式(12)--结构型之代理模式(Proxy Pattern)

"围观"设计模式(14)--结构型之外观模式(Facade Pattern)

"围观"设计模式(11)--结构型之适配器模式(Adapter Pattern)

"围观"设计模式(17)--结构型之享元模式(Flyweight Pattern)

&quot;围观&quot;设计模式--里氏替换原则(LSP,Liskov Substitution Principle)