0%

职责链模式(Chain of Responsibility)

引子

设计模式的六大原则

职责链模式(Chain of Responsibility)

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

何时使用:在处理消息的时候以过滤很多道。

如何解决:拦截的类都实现统一接口。

关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

定义与特点

定义

把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这个方式去除对象之间的耦合。

主要优点

1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。

主要缺点

1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。

结构与实现

结构

角色有哪些?

  1. 抽象责任链构件: 聚合自身。调用时如果发现有聚合项,传递责任给聚合项。
  2. 实现责任链构件:真实责任构件。

设计图

实现

写实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System;

namespace ChainofResponsibility
{
/// <summary>
/// 抽象责任链构件
/// </summary>
abstract class AbstractLogger
{
public const int INFO = 1;
public const int DEBUG = 2;
public const int ERROR = 3;

protected int level;
private AbstractLogger nextNode;

public void SetNextNode(AbstractLogger logger)
{
nextNode = logger;
}

public void Handle(int level, string msg)
{
if (level >= this.level)
{
Operation(msg);
}
if (nextNode != null)
{
nextNode.Handle(level, msg);
}
}

protected abstract void Operation(string msg);
}
/// <summary>
/// 控制台输出日志
/// </summary>
class ConsoleLogger : AbstractLogger
{
public ConsoleLogger(int level)
{
this.level = level;
}
protected override void Operation(string msg)
{
Console.WriteLine("Standard Console::Logger: " + msg);
}
}
/// <summary>
/// 文件输出日志
/// </summary>
class FileLogger : AbstractLogger
{
public FileLogger(int level)
{
this.level = level;
}
protected override void Operation(string msg)
{
Console.WriteLine("File Console::Logger: " + msg);
}
}
/// <summary>
/// 远程输出日志
/// </summary>
class RemoteLogger : AbstractLogger
{
public RemoteLogger(int level)
{
this.level = level;
}

protected override void Operation(string msg)
{
Console.WriteLine("Remote Console::Logger: " + msg);
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;

namespace ChainofResponsibility
{
class Program
{
static void Main(string[] args)
{
AbstractLogger abstractLogger = GetLogger();

abstractLogger.Handle(AbstractLogger.INFO, "This is an Info Message");
abstractLogger.Handle(AbstractLogger.DEBUG, "This is an Debug Message");
abstractLogger.Handle(AbstractLogger.ERROR, "This is an Error Message");

Console.ReadLine();
}
/// <summary>
/// 这里容易出现 循环调用,不直观,有碍于查错误.
/// </summary>
/// <returns></returns>
static AbstractLogger GetLogger()
{
AbstractLogger remoteLogger = new RemoteLogger(AbstractLogger.DEBUG);
AbstractLogger fileLogger = new FileLogger(AbstractLogger.ERROR);
AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

remoteLogger.SetNextNode(fileLogger);
fileLogger.SetNextNode(consoleLogger);
return remoteLogger;
}
}
}

应用场景

1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求

扩展

欢迎关注我的其它发布渠道