职责模式

定义

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

职责模式也称为责任链模式,它将请求的发送者和接收者解耦了。客户端不需要知道请求处理者的明确信息和处理的具体逻辑,甚至不需要知道链的结构,它只需要将请求进行发送即可。

模型说明

1.设计要点在设计职责模式的程序时要注意以下几点。

(1)请求者与请求内容:确认谁要发送请求,发送请求的对象称为请求者。请求的内容通过发送请求时的参数进行传递。

(2)有哪些责任人:责任人是构成责任链的关键要素。请求的流动方向是链条中的线,而责任人则是链条上的节点,线和节点共同构成了一条链条。

(3)对责任人进行抽象:真实世界中的责任人多种多样,纷繁复杂,有不同的职责和功能;但他们也有一个共同的特征—都可以处理请求。所以需要对责任人进行抽象,使他们具有责任的可传递性。

(4)责任人可自由组合:责任链上的责任人可以根据业务的具体逻辑进行自由的组合和排序。

2.职责模式的优缺点

优点:

(1)降低耦合度。它将请求的发送者和接收者解耦。

(2)简化了对象。它使得对象不需要知道链的结构。

(3)增强给对象指派职责的灵活性。可改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任人。

(4)增加新的处理类很方便。

缺点:

(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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

"""职责模式,责任链模式"""
from abc import ABCMeta, abstractmethod


class Request(object):
"""请求内容"""
def __init__(self, name, dayoff, reason):
self.__name = name
self.__dayoff = dayoff
self.__reason = reason

def get_dayoff(self):
return self.__dayoff

def get_reason(self):
return self.__reason

def get_name(self):
return self.__name



class Responsible(metaclass=ABCMeta):
"""责任人抽象"""
def __init__(self, name, title):
self.__name = name
self.__title = title
self.__next_handler = None

def get_name(self):
return self.__name

def get_title(self):
return self.__title

def set_next_handler(self, next_handler):
self.__next_handler = next_handler

def get_next_handler(self):
return self.__next_handler

def handler_request(self, request):
"""请求处理, 当前责任人处理请求"""
self._handler_request(request)
if self.__next_handler is not None:
self.__next_handler.handler_request(request)

@abstractmethod
def _handler_request(self, request):
"""真正的处理函数"""
pass


class Person(object):
def __init__(self, name):
self.__name = name
self.__leader = None

def set_name(self, name):
self.__name = name

def get_name(self):
return self.__name

def set_leader(self, leader):
self.__leader = leader

def get_leader(self):
return self.__leader

def send_request(self, request):
print(f"{self.__name} 申请请假 {request.get_dayoff()} 天")
if self.__leader is not None:
self.__leader.handler_request(request)


class Supervisor(Responsible):
def __init__(self, name, title):
super().__init__(name, title)

def _handler_request(self, request):
day_off = request.get_dayoff()
if day_off <= 2:
print(f"同意 {request.get_name()} 请假,签字人: {self.get_name()}")


class DepartmentManager(Responsible):
def __init__(self, name, title):
super().__init__(name, title)

def _handler_request(self, request):
day_off = request.get_dayoff()
if day_off > 2 and day_off <= 5:
print(f"同意 {request.get_name()} 请假,签字人: {self.get_name()}")


class CEO(Responsible):
def __init__(self, name, title):
super().__init__(name, title)

def _handler_request(self, request):
day_off = request.get_dayoff()
if day_off > 5 and day_off <= 22:
print(f"同意 {request.get_name()} 请假,签字人: {self.get_name()}")


class Administrator(Responsible):
def __init__(self, name, title):
super().__init__(name, title)

def _handler_request(self, request):
print(f"{request.get_name()} 请假申请已审核,已备案处理,签字人: {self.get_name()}")


if __name__ == "__main__":
supervisor = Supervisor('lzk', '项目经理')
department_mgr = DepartmentManager('lzh', '区域总监')
ceo = CEO('lwl', 'CEO')
admin = Administrator('ylp', 'HRBP')

supervisor.set_next_handler(department_mgr)
department_mgr.set_next_handler(ceo)
ceo.set_next_handler(admin)

print('*' * 60)
sunny = Person('sunny')
sunny.set_leader(supervisor)
sunny.send_request(Request(sunny.get_name(), 1, '参加大会'))

print('*' * 60)
tonny = Person('tonny')
tonny.set_leader(supervisor)
tonny.send_request(Request(tonny.get_name(), 5, '家里有事'))

print('*' * 60)
punny = Person('punny')
punny.set_leader(supervisor)
punny.send_request(Request(punny.get_name(), 15, '出国深造'))


输出:
************************************************************
sunny 申请请假 1
同意 sunny 请假,签字人: lzk
sunny 请假申请已审核,已备案处理,签字人: ylp
************************************************************
tonny 申请请假 5
同意 tonny 请假,签字人: lzh
tonny 请假申请已审核,已备案处理,签字人: ylp
************************************************************
punny 申请请假 15
同意 punny 请假,签字人: lwl
punny 请假申请已审核,已备案处理,签字人: ylp