python 设计模式之责任链模式

coolpython

共 3429字,需浏览 7分钟

 ·

2022-04-28 23:27

1. 责任链模式

通俗点讲,责任链是一个链表结构,这条链上有多个节点,它们有相同的接口,各自有各自的责任和实现。当有数据输入时,第一个节点看自己能否处理问题,如果可以就进行处理,如果不能就数据交给下一个节点进行处理,以此类推直到最后一个责任节点。

上面这段描述里,我们可以总结出以下几个关键信息

  1. 链表

  2. 相同的接口

  3. 节点有各自的任务

  4. 从第一个节点开始处理输入,如果不能处理,交给下一个节点

为了实现相同的接口,在责任链模式中需要一个抽象处理者角色来定义一个抽象接口,责任链上的节点是具体处理者角色,处理者必须实现由抽象处理者定义的抽象接口并各自实现具体功能。

2. 责任链模式示例

在网站上设置密码时,对密码通常有如下要求:

  1. 密码长度大于6

  2. 包含小写字母和大写字母

  3. 包含特殊字符

我就以检查密码是否合法为例子讲解如何实现责任链模式,当然,实践中这样的检查是不需要使用责任链来实现的,只是这个例子更通俗易懂一些。

2.1 抽象处理者角色

from abc import ABC, abstractmethod


class AbcCheckHandler(ABC):
@abstractmethod
def check_password(self, password):
pass

@abstractmethod
def set_next(self, handler):
pass

AbcCheckHandler 类是抽象处理者角色,它存在的意义是定义具体处理者角色必须实现的接口,这样处理者角色在使用时才能规范行为。

2.2 具体处理者角色

具体处理者角色是抽象处理者角色的子类

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,但那样很多代码都会重复。

2.3 调用责任链

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")

对于责任链的调用者,你不必关心链上有多少个节点,节点的顺序是什么,这些都是在创建责任链时决定的,由创建者负责,你只需要将数据输入给责任链即可。

3. 责任链模式的优缺点

优点:

  1. 增加或者删除责任很方便

  2. 降低耦合度,对于请求的发送者,无需关心接收者都有哪些,顺序如何

缺点:

  1. 可能会在程序调试方面制造一些麻烦,但可以通过合理的日志输出来规避


浏览 115
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报