[size=large]1、意图
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之前的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
2、动机
考虑一个图形用户界面中的上下文有关的帮助机制。用户在界面的任一部分上点击就可以得到帮助信息,所提供的帮助依赖于点击的是界面的哪一部分以及其上下文。例如,对话框中的按钮的帮助信息就可能和主窗口中类似的按钮不同。如果对那一部分界面没有特定的帮助信息,那么帮助系统应该显示一个关于当前上下文的较一般的帮助信息——比如说,整个对话框。
因此很自然地,应根据普遍性(generality)即从最特殊到最普通的顺序来组织帮助信息。而且,很明显,在这些用户界面对象中会有一个对象来处理帮助请求;至于是哪一个对象则取决于上下文以及可用的帮助具体到何种程度。
这儿的问题是提交帮助请求的对象(如按钮)并不明确知道是谁是最终提供帮助的对象。我们要有一种办法将提交帮助请求的对象与可能提供帮助信息的对象解耦(decouple)。Chain of Responsibility模式告诉我们应该怎么做。
这一模式的想法是,给多个对象处理一个请求的机会,从而解耦发送者和接收者。该请求沿对项链直至其中的一个对象处理它,如下图所示。
[img]http://dl2.iteye.com/upload/attachment/0085/5059/cb8d2717-ef6c-3eec-8e15-dbe5dbd0390f.jpg[/img]
从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转给链中的下一个候选者。提交请求的对象并不明确地知道哪一个对象将会处理它——我们说该请求有一个隐士接受者(implicit receiver)。
3、适用性
在以下条件下使用Responsibility链:
有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
4、结构
[img]http://dl2.iteye.com/upload/attachment/0085/5068/6e8deb49-dfdb-3195-9b1a-c943d4018c85.jpg[/img]
5、参与者
Handle
——定义一个处理请求的接口
——(可选)实现后继链。
ConcreteHandler
——处理它所负责的请求
——可访问它的后继者
——如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
Client
——向链上的具体处理者(ConcreteHandler)对象提交请求。
6.代码示例
[/size]
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之前的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
2、动机
考虑一个图形用户界面中的上下文有关的帮助机制。用户在界面的任一部分上点击就可以得到帮助信息,所提供的帮助依赖于点击的是界面的哪一部分以及其上下文。例如,对话框中的按钮的帮助信息就可能和主窗口中类似的按钮不同。如果对那一部分界面没有特定的帮助信息,那么帮助系统应该显示一个关于当前上下文的较一般的帮助信息——比如说,整个对话框。
因此很自然地,应根据普遍性(generality)即从最特殊到最普通的顺序来组织帮助信息。而且,很明显,在这些用户界面对象中会有一个对象来处理帮助请求;至于是哪一个对象则取决于上下文以及可用的帮助具体到何种程度。
这儿的问题是提交帮助请求的对象(如按钮)并不明确知道是谁是最终提供帮助的对象。我们要有一种办法将提交帮助请求的对象与可能提供帮助信息的对象解耦(decouple)。Chain of Responsibility模式告诉我们应该怎么做。
这一模式的想法是,给多个对象处理一个请求的机会,从而解耦发送者和接收者。该请求沿对项链直至其中的一个对象处理它,如下图所示。
[img]http://dl2.iteye.com/upload/attachment/0085/5059/cb8d2717-ef6c-3eec-8e15-dbe5dbd0390f.jpg[/img]
从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转给链中的下一个候选者。提交请求的对象并不明确地知道哪一个对象将会处理它——我们说该请求有一个隐士接受者(implicit receiver)。
3、适用性
在以下条件下使用Responsibility链:
有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
4、结构
[img]http://dl2.iteye.com/upload/attachment/0085/5068/6e8deb49-dfdb-3195-9b1a-c943d4018c85.jpg[/img]
5、参与者
Handle
——定义一个处理请求的接口
——(可选)实现后继链。
ConcreteHandler
——处理它所负责的请求
——可访问它的后继者
——如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
Client
——向链上的具体处理者(ConcreteHandler)对象提交请求。
6.代码示例
[/size]
package chainofresp;
abstract class Logger {
public static int ERR = 3;
public static int NOTICE = 5;
public static int DEBUG = 7;
protected int mask;
// The next element in the chain of responsibility
protected Logger next;
public void setNext(Logger log) {
next = log;
}
public void message(String msg, int priority) {
if (priority <= mask) {
writeMessage(msg);
}
if (next != null) {
next.message(msg, priority);
}
}
abstract protected void writeMessage(String msg);
}
class StdoutLogger extends Logger {
public StdoutLogger(int mask) {
this.mask = mask;
}
protected void writeMessage(String msg) {
System.out.println("Writing to stdout: " + msg);
}
}
class EmailLogger extends Logger {
public EmailLogger(int mask) {
this.mask = mask;
}
protected void writeMessage(String msg) {
System.out.println("Sending via email: " + msg);
}
}
class StderrLogger extends Logger {
public StderrLogger(int mask) {
this.mask = mask;
}
protected void writeMessage(String msg) {
System.err.println("Sending to stderr: " + msg);
}
}
public class ChainOfResponsibilityExample {
private static Logger createChain() {
// Build the chain of responsibility
Logger logger = new StdoutLogger(Logger.DEBUG);
Logger logger1 = new EmailLogger(Logger.NOTICE);
logger.setNext(logger1);
Logger logger2 = new StderrLogger(Logger.ERR);
logger1.setNext(logger2);
return logger;
}
public static void main(String[] args) {
Logger chain = createChain();
// Handled by StdoutLogger (level = 7)
chain.message("Entering function y.", Logger.DEBUG);
// Handled by StdoutLogger and EmailLogger (level = 5)
chain.message("Step1 completed.", Logger.NOTICE);
// Handled by all three loggers (level = 3)
chain.message("An error has occurred.", Logger.ERR);
}
}
/*
The output is:
Writing to stdout: Entering function y.
Writing to stdout: Step1 completed.
Sending via e-mail: Step1 completed.
Writing to stdout: An error has occurred.
Sending via e-mail: An error has occurred.
Writing to stderr: An error has occurred.
*/