【问题标题】:When do we need decorator pattern?我们什么时候需要装饰器模式?
【发布时间】:2011-03-29 12:33:34
【问题描述】:

什么时候需要使用装饰器模式?如果可能,请给我一个非常适合该模式的真实示例。

【问题讨论】:

  • 如果您想知道装饰器模式是否有用,您需要告诉我们您需要做什么,如果您只是想要一个通用示例,只需在维基百科上查找装饰器模式。
  • @BenRobinson 我已经阅读了Wikipedia article,并且仍在寻找更好的例子。

标签: design-patterns decorator


【解决方案1】:

Java 中的 Streams - InputStreamOutputStream 的子类是装饰器模式的完美示例。

例如,将文件写入磁盘:

File toWriteTo = new File("C:\\temp\\tempFile.txt");
OutputStream outputStream = new FileOutputStream(toWriteTo);    

outputStream.write("Sample text".getBytes());

那么您是否需要一些关于写入磁盘的额外功能:

File toWriteTo = new File("C:\\temp\\tempFile.txt");
OutputStream outputStream = 
             new GZIPOutputStream(new FileOutputStream(toWriteTo));

outputStream.write("Sample text".getBytes());

通过简单地“链接”构造函数,您可以创建非常强大的写入磁盘的方法。这种方式的美妙之处在于您可以稍后添加不同的(在此示例中)OutputStream 实现。此外,每个实现都不知道其他实现是如何工作的——它们都只是按照同一个合同工作。这也使得单独测试每个实现变得非常容易。


有很多“现实世界”的例子可以使用装饰器模式。在我的脑海中,一些例子:
  • 读写磁盘(上图)
  • UI 元素的构造,例如在文本区域上添加滚动条等

Head First Design Patterns 有更多“真实世界”的示例。 O'Reilly 似乎有免费的示例章节,即装饰器模式;谷歌显示了这个链接:PDF

【讨论】:

  • 是的,java.io 完全是关于装饰器的。
  • +1 虽然我不认为 java.io 中大量使用装饰器模式是“美丽的”。这是 Java 中的文件 io 在 a** 中如此痛苦的各种原因之一。
【解决方案2】:

两个现实生活中的例子:

暗黑破坏神 2 和最终幻想 7 中的物品升级系统。武器和盔甲有插槽或插槽。在游戏过程中,玩家将升级(宝石、符文或材料)放入这些插槽中。每次升级都有单独的效果(例如,8 点火焰伤害或 10% 法力吸取)。因此,当您挥动剑时,它会造成基础伤害加上您添加的每次升级所增加的伤害。这与装饰器模式非常匹配。

【讨论】:

  • 是用装饰器模式实现的吗?似乎策略列表也可以。
  • @JosiahYoder 在策略模式中的行为在运行时发生变化,一次只有一个,但在装饰器模式中,您可以向现有行为添加其他行为。
  • @HameedSyed 暗黑破坏神或最终幻想 7 “插槽”或​​“升级”是否充当对象?装饰器模式在装饰器和被装饰对象之间也有“is-a”关系。这里的装饰器是什么?装饰对象是什么?
  • @JosiahYoder 我不知道这个游戏,但我可以用一个文件流示例来解释,如果可能的话,你可以与游戏相关。考虑一个必须实现 InputStream 才能正常工作的文件流,现在这是“是一个”关系并且是一个装饰器。但是你想再次增加这个文件流的速度,所以你用 BufferInputStream 装饰。现在你又想压缩这个 BufferInputStream ,所以你装饰更多添加 ZipStream 等等。这个额外的装饰(BufferInputStream ,ZipStream )到装饰对象(filestream )是一个装饰器模式。
  • @HameedSyed 谢谢。我希望可以充实视频游戏示例。我在我的课程中使用了输入流示例,但正在寻找学生可以更好地理解的东西。
【解决方案3】:

来自四人组:

例如,图形用户界面工具包应该允许您向任何用户界面组件添加边框等属性或滚动等行为。

...

装饰器符合它所装饰的组件的接口,因此它的存在对组件的客户端是透明的。装饰器将请求转发给组件,并且可能会在转发之前或之后执行其他操作(例如绘制边框)。透明度允许您递归嵌套装饰器,从而允许无限数量的附加职责。

【讨论】:

  • 现实世界的 UI 使用这种装饰器吗?
【解决方案4】:

看看 Fowler 的描述;它给出了一个与书籍/视频相关的具体示例和一个“可借”的装饰器,你可以找到它here

【讨论】:

    【解决方案5】:

    我见过的最酷且最直接的用途之一是实现撤消能力,这可以追溯到单级撤消的糟糕时代。给定一个矢量绘图程序,选择了几个不同颜色的对象:执行一个命令来更改它们的所有颜色。并使其可撤销。这是通过应用一个装饰器来完成的,该装饰器在 getColor() 流中被调用,因此当它们被绘制时,它们被绘制成新的颜色;本质上,对象自己的 getColor() 方法被否决了。所以他们以新的颜色出现了。撤消就像从所有对象中删除装饰器一样简单;提交动作是将装饰器中的颜色应用到对象上,然后将其移除。比保存一张表格简单得多,其中列出了哪些对象已被着色以及它们的原始颜色是什么。

    【讨论】:

      【解决方案6】:

      装饰器模式的目的是:

      动态地为对象附加额外的职责。装饰器为扩展功能提供了一种灵活的替代子类的方法。 [通过 Head First:设计模式]

      装饰器模式最常用的是 GUI 和 java.io 类。 Head First: Design Patterns 有一个关于装饰器模式[link] 的免费章节,其中提供了一些其他示例:

      我们将重新审视典型的过度使用 继承,你将学习如何 使用在运行时装饰你的类 对象组合的一种形式。为什么? 一旦你知道了技术 装饰,你可以给 你(或其他人)的新物品 不承担任何责任 底层代码更改 类。

      您还可以阅读 Decorator Pattern by Example [PDF],其中在评估应用程序中使用了装饰器模式。

      【讨论】:

      • Head First PDF 链接是 404。
      • @james.garriss:已修复
      【解决方案7】:

      您要求提供一个真实世界的示例,因此您可以:从 github 下载(或浏览)DonsProxy

      git://github.com/DonBranson/DonsProxy.git

      DonsProxy 基本上使用 WireTap 模式让您监视或提取 HTTP 流量,此外它还允许您修改连接行为以模拟次优连接。我使用装饰器模式根据用户选项修改通道。命令行或 GUI 选项(取决于他们使用的视图)允许延迟注入和带宽注入等。当他们注入延迟时,这会将 LatencyDecorator 添加到通道中;如果他们限制带宽,则会将 ThrottleDecorator 添加到通道中。由于这使用了装饰器模式,因此他们可以根据自己的喜好混合搭配行为。

      【讨论】:

      • @JosiahYoder - 更新了链接。谢谢!
      • 加入一个小code-sn-ps来完成这个例子也不错,减少对链接的依赖。
      【解决方案8】:

      如果您熟悉 Java 中的 Swing 开发(以及其他 GUI 工具包),您会发现装饰器模式被大量使用。你可能有一个构造函数,它接收一个特定的组件,然后向它添加功能。

      这里是a good article that uses Swing as an example

      【讨论】:

        【解决方案9】:

        什么时候需要使用装饰器模式?

        如果

        使用Decorator_pattern
        1. 应动态添加/删除对象职责和行为
        2. 具体实施应与职责和行为分离
        3. 子类化成本太高,无法动态添加/删除职责

        如果可能,请给我一个非常适合该模式的真实示例。

        我想出了我自己的自动售货机装饰器。

        问题陈述:通过添加一种或多种口味(如糖、柠檬等)来计算饮料(茶或咖啡)的价格。

        代码示例和解释可用@

        When to Use the Decorator Pattern?

        【讨论】:

          猜你喜欢
          • 2010-09-21
          • 2011-01-02
          • 1970-01-01
          • 2019-01-18
          • 2018-04-17
          • 1970-01-01
          • 2019-07-17
          • 2019-06-28
          • 1970-01-01
          相关资源
          最近更新 更多