对「装饰模式」的简单理解

notebook

在前文 设计模式 - 装饰模式 中比较全面地介绍了什么是装饰模式,介绍了设计模式 - 装饰模式优缺点、适用范围。
现在简单实现一下,加深学习印象。

我们可以这样理解:

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰模式特点

  1. 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
  2. 装饰对象包含一个真实对象的引用(reference)
  3. 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  4. 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

真实对象区别于抽象对象(Component)。抽象对象不应该被具体实现;同时修饰类引用和继承 Component 类,具体扩展类重写父类方法。

设计原则

  1. 应当多组合,少继承

利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

  1. 类的设计应该对扩展开放,对修改关闭

样例实现

在这个样例中,主要体会对子类的组合实现,以及深入体会如何动态加载子类

from functools import wraps


def login_check(func):
"""
Decorator
check whether user is logged in
:param func
:return wrapper
"""
@wraps(func)
def wrapper(*args, **kwargs):
if args[0].status != "login":
print("User hasn't logged in yet!")
else:
return func(*args, **kwargs)
return wrapper


class Visitor(object):
def __init__(self, status) -> None:
self.status = status

# decorate this method
@login_check
def access_allow(self):
print("User now has login. Access is allowed")


if __name__ == "__main__":
print('>>> set status login, is result')
visitor = Visitor('login')
visitor.access_allow()
print('>>> set status not login, below is result')
visitor = Visitor('visitor')
visitor.access_allow()

Console Output :
> set status login, is result
[LOGIN RESULT] User now has login. Access is allowed
>set status not login, below is result
[LOGIN RESULT] User hasn’t logged in yet!

接下来新增一个函数,命名为logger,目的是显示日志,当他装饰的函数被调用时,就会记录日志,内容包括函数名以及函数参数。

from functools import wraps


def login_check(func):
...


def logger(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"{func.__name__} was called. Parmas: {str(args)}, {str(kwargs)}")
return func(*args, **kwargs)
return wrapper


class Visitor(object):
def __init__(self, status) -> None:
self.status = status

# decorate this method
@logger
@login_check
def access_allow(self):
print("[LOGIN RESULT] User now has login. Access is allowed")


if __name__ == "__main__":
print('> set status login, is result')
visitor = Visitor('login')
visitor.access_allow()
print('> set status not login, below is result')
visitor = Visitor('visitor')
visitor.access_allow()

Console Output :
> set status login, is result
access_allow was called. Parmas: (<__main__.Visitor object at 0x0000019BCE620F70>,), {}
[LOGIN RESULT] User now has login. Access is allowed
>set status not login, below is result
access_allow was called. Parmas: (<__main__.Visitor object at 0x0000019BCE620730>,), {}
[LOGIN RESULT] User hasn’t logged in yet!

Author: DioPong

Permalink: https://blog.2to.fun/post/notebook/Structure-Decoration-comprehend/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。

Comments

Unable to load Disqus, please make sure your network can access.