通俗点讲,责任链是一个链表结构,这条链上有多个节点,它们有相同的接口,各自有各自的责任和实现。当有数据输入时,第一个节点看自己能否处理问题,如果可以就进行处理,如果不能就数据交给下一个节点进行处理,以此类推直到最后一个责任节点。
上面这段描述里,我们可以总结出以下几个关键信息
为了实现相同的接口,在责任链模式中需要一个抽象处理者角色来定义一个抽象接口,责任链上的节点是具体处理者角色,处理者必须实现由抽象处理者定义的抽象接口并各自实现具体功能。
在网站上设置密码时,对密码通常有如下要求:
我就以检查密码是否合法为例子讲解如何实现责任链模式,当然,实践中这样的检查是不需要使用责任链来实现的,只是这个例子更通俗易懂一些。
from abc import ABC, abstractmethod
class AbcCheckHandler(ABC):
@abstractmethod
def check_password(self, password):
pass
@abstractmethod
def set_next(self, handler):
pass
AbcCheckHandler 类是抽象处理者角色,它存在的意义是定义具体处理者角色必须实现的接口,这样处理者角色在使用时才能规范行为。
具体处理者角色是抽象处理者角色的子类
class CheckHanlderBase(AbcCheckHandler):
_next_handler = None
def set_next(self, handler):
self._next_handler = handler
@abstractmethod
def _check(self, password):
pass
def check_password(self, password):
status, msg = self._check(password)
if status:
if self._next_handler:
return self._next_handler.check_password(password)
else:
return True, ''
else:
return status, msg
class LengthCheckHandler(CheckHanlderBase):
"""
专门检查长度
"""
def _check(self, password):
if len(password) > 6:
return True, ''
return False, '长度错误'
class CaseCheckHandler(CheckHanlderBase):
"""
专门检查大小写
"""
def _check(self, password):
has_lower = False
has_upper = False
for letter in password:
if 'a' < letter < 'z':
has_lower = True
if 'A' < letter < 'Z':
has_upper = True
if has_lower and has_upper:
return True, ''
else:
return False, '大小写不符合要求'
class SpecialCheckHandler(CheckHanlderBase):
def _check(self, password):
for letter in ('!', '@', '#', '$'):
if letter in password:
return True, ''
return False, '未包含特殊字符'
def check_password(password):
len_checker = LengthCheckHandler()
case_checker = CaseCheckHandler()
special_checker = SpecialCheckHandler()
len_checker.set_next(case_checker)
case_checker.set_next(special_checker)
status, msg = len_checker.check_password(password)
if status:
print(f"{password} 检查通过")
else:
print(f"{password} 检查不通过: {msg}")
LengthCheckHandler, CaseCheckHandler, SpecialCheckHandler这3个类是具体处理者角色,他们是CheckHanlderBase的子类,而CheckHanlderBase 是AbcCheckHandler的子类,我特地增加了CheckHanlderBase,为的是让代码更加简洁,你可以去掉它,让三个检查类直接继承AbcCheckHandler,但那样很多代码都会重复。
def get_password_checker():
len_checker = LengthCheckHandler()
case_checker = CaseCheckHandler()
special_checker = SpecialCheckHandler()
len_checker.set_next(case_checker)
case_checker.set_next(special_checker)
return len_checker
def check_password(password):
password_checker = get_password_checker()
status, msg = password_checker.check_password(password)
if status:
print(f"{password} 检查通过")
else:
print(f"{password} 检查不通过: {msg}")
if __name__ == "__main__":
check_password("1324sfED!")
check_password("323!")
check_password("323df3!")
check_password("323DKS3!")
check_password("skdjOWRJ")
对于责任链的调用者,你不必关心链上有多少个节点,节点的顺序是什么,这些都是在创建责任链时决定的,由创建者负责,你只需要将数据输入给责任链即可。
优点:
缺点:
QQ交流群: 211426309