设计模式学习(九)——职责链模式

职责链模式定义

职责链模式(Chain of Responsibility Pattern)避免请求发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

在客户端创建好传递链之后,发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

值得注意的是,如果建链不当,可能会造成循环调用,将导致系统陷入死循环。


职责链模式结构图

图中:

  • Handler表示抽象传递者,它定义了一个处理请求的接口,并且在Handler中定义了后继对象,其后继对象类型为Handler,可以在Handler中编写代码实现后继链的设置;

  • ConcreteHandler表示具体传递者,处理它所负责的请求,并可以访问链中下一个对象,当有请求发送过来时,如果能够处理该请求就处理它,否则将请求转发给后继者;

  • Client表示客户类,它向链中的对象提出最初的请求。


职责链模式实例——在线文档帮助系统

实例说明

某公司欲开发一个软件系统的在线文档帮助系统,用户可以在任何一个查询环境中输入查询关键字,如果当前查询环境下没有相关内容,则系统会将查询按照一定的顺序转发给其他查询环境。基于上述需求,采用职责链模式对该系统进行设计。

实例类图

实例类图中与职责链模式结构图对应的类主要有:

  • SearchContext抽象类充当抽象处理者(抽象传递者);

  • JavaSearchContext、SQLSearchContext和UMLSearchContext充当具体处理者(具体传递者);

  • Client为客户类。

实例代码

SearchContext.java:

//抽象查询请求处理上下文类:抽象传递者
abstract class SearchContext
{
protected SearchContext successor;
public void setSuccessor(SearchContext successor)
{

this.successor = successor;
}
public abstract void search(String keyword);
}

JavaSearchContext.java:

//具体查询请求处理上下文类:具体传递者
class JavaSearchContext extends SearchContext
{

public void search(String keyword)
{
//模拟实现
if(keyword.contains("Java"))
{
System.out.println("查询关键字Java!");
}
else
{
successor.search(keyword);
}
}
}

SQLSearchContext.java:

//具体查询请求处理上下文类:具体传递者
class SQLSearchContext extends SearchContext
{

public void search(String keyword)
{
//模拟实现
if(keyword.contains("SQL"))
{
System.out.println("查询关键字SQL!");
}
else
{
successor.search(keyword);
}
}
}

UMLSearchContext.java:

//具体查询请求处理上下文类:具体传递者
class UMLSearchContext extends SearchContext
{

public void search(String keyword)
{
//模拟实现
if(keyword.contains("UML"))
{
System.out.println("查询关键字UML!");
}
else
{
successor.search(keyword);
}
}
}

Client.java:

//客户端测试类
class Client
{
public static void main(String args[])
{

SearchContext jContext,sContext,uContext;
jContext = new JavaSearchContext();
sContext = new SQLSearchContext();
uContext = new UMLSearchContext();
jContext.setSuccessor(sContext);
sContext.setSuccessor(uContext);
String keyword = "UML类图绘制疑惑";
jContext.search(keyword);
}
}

运行结果

附加描述

在本实例中,客户端测试类创建了职责链,当向jContext对象传递查询关键字“UML类图绘制疑惑”时,jContext首先处理该关键字,如果不能处理则转发请求给它的后继者,直到链上某一个对象能够处理该关键字请求,对于该关键字,请求转发顺序为jContext->sContext->uContext,最后由uContext对象处理该请求。职责链由客户端创建,因此请求的传递顺序也由客户端来确定。


后话

职责链模式就好像流水线加工一样,对于一个客户请求,在线上不断传递下去,看线上哪个工人能处理好这个请求。

这个模式的实例代码很精辟,看完之后,捋顺了代码流程,不禁赞叹!