装饰器方法 - Python设计模式
装饰器方法是一种结构设计模式,它允许您通过将这些对象放置在包含行为的包装器对象中来动态地将新行为附加到对象而不更改它们的实现。
由于其内置功能,在Python中实现装饰器方法要容易得多。它不等同于继承,因为新功能仅添加到该特定对象,而不是整个子类。
不使用装饰器方法的问题
想象一下,我们正在使用一种格式工具,该工具提供诸如加粗文本和下划线等功能。但一段时间后,我们的格式化工具在目标受众中广为人知,并且根据我们得到的反馈,我们的受众希望应用程序具有更多功能,例如将文本设置为斜体和许多其他功能。
看起来很简单?在不干扰现有客户端代码的情况下实现这一点或扩展我们的类以添加更多功能并不是一件容易的事,因为我们必须维护单一责任原则。
使用装饰器方法的解决方案
现在让我们看看我们必须避免这种情况的解决方案。最初,我们只有WrittenText ,但我们必须应用BOLD、ITALIC、UNDERLINE等过滤器。因此,我们将为每个函数创建单独的包装类,例如 BoldWrapperClass、ItalicWrapperClass 和 UnderlineWrapperclass。
首先,我们将在 Written 文本上调用 BoldWrapperclass,最终将文本转换为 BOLD 字母
然后我们将 ItalicWrapperClass 和 UnderlineWrapperClass 应用到 Bold 文本上,这将为我们提供我们想要的结果。
以下代码是使用装饰器方法编写的:
Python3
class WrittenText:
"""Represents a Written text """
def __init__(self, text):
self._text = text
def render(self):
return self._text
class UnderlineWrapper(WrittenText):
"""Wraps a tag in """
def __init__(self, wrapped):
self._wrapped = wrapped
def render(self):
return "{}".format(self._wrapped.render())
class ItalicWrapper(WrittenText):
"""Wraps a tag in """
def __init__(self, wrapped):
self._wrapped = wrapped
def render(self):
return "{}".format(self._wrapped.render())
class BoldWrapper(WrittenText):
"""Wraps a tag in """
def __init__(self, wrapped):
self._wrapped = wrapped
def render(self):
return "{}".format(self._wrapped.render())
""" main method """
if __name__ == '__main__':
before_gfg = WrittenText("GeeksforGeeks")
after_gfg = ItalicWrapper(UnderlineWrapper(BoldWrapper(before_gfg)))
print("before :", before_gfg.render())
print("after :", after_gfg.render())
装饰器方法的类图
下面是装饰器方法的类图:
好处
- 单一职责原则:使用装饰器方法很容易将实现许多可能的行为变体的整体类划分为多个类。
- 运行时职责:我们可以在运行时轻松地从对象中添加或删除职责。
- 子类化:装饰器模式是子类化的替代方案。子类化在编译时添加行为,并且更改会影响原始类的所有实例;装饰可以在运行时为单个对象提供新的行为。
缺点
- 移除 Wrapper:很难从 wrappers 堆栈中移除特定的 wrapper。
- 复杂的装饰器:让装饰器跟踪其他装饰器可能很复杂,因为回顾装饰器链的多层开始将装饰器模式推到超出其真实意图的范围内。
- 丑陋的配置:大量的层代码可能会使配置丑陋。
适用性
- 无法继承:通常,当无法使用继承扩展对象的行为时,使用装饰器方法。
- 运行时分配:装饰器方法最重要的功能之一是在运行时为对象分配不同且独特的行为。
进一步阅读Java中的装饰器设计模式