
通俗点讲,责任链是一个链表结构,这条链上有多个节点,它们有相同的接口,各自有各自的责任和实现。当有数据输入时,第一个节点看自己能否处理问题,如果可以就进行处理,如果不能就数据交给下一个节点进行处理,以此类推直到最后一个责任节点。
上面这段描述里,我们可以总结出以下几个关键信息
为了实现相同的接口,在责任链模式中需要一个抽象处理者角色来定义一个抽象接口,责任链上的节点是具体处理者角色,处理者必须实现由抽象处理者定义的抽象接口并各自实现具体功能。
在网站上设置密码时,对密码通常有如下要求:
我就以检查密码是否合法为例子讲解如何实现责任链模式,当然,实践中这样的检查是不需要使用责任链来实现的,只是这个例子更通俗易懂一些。
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
 
                        分享日常研究的python技术和遇到的问题及解决方案