【发布时间】:2011-03-29 12:33:34
【问题描述】:
什么时候需要使用装饰器模式?如果可能,请给我一个非常适合该模式的真实示例。
【问题讨论】:
-
如果您想知道装饰器模式是否有用,您需要告诉我们您需要做什么,如果您只是想要一个通用示例,只需在维基百科上查找装饰器模式。
-
@BenRobinson 我已经阅读了Wikipedia article,并且仍在寻找更好的例子。
什么时候需要使用装饰器模式?如果可能,请给我一个非常适合该模式的真实示例。
【问题讨论】:
Java 中的 Streams - InputStream 和 OutputStream 的子类是装饰器模式的完美示例。
例如,将文件写入磁盘:
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 实现。此外,每个实现都不知道其他实现是如何工作的——它们都只是按照同一个合同工作。这也使得单独测试每个实现变得非常容易。
Head First Design Patterns 有更多“真实世界”的示例。 O'Reilly 似乎有免费的示例章节,即装饰器模式;谷歌显示了这个链接:PDF
【讨论】:
两个现实生活中的例子:
暗黑破坏神 2 和最终幻想 7 中的物品升级系统。武器和盔甲有插槽或插槽。在游戏过程中,玩家将升级(宝石、符文或材料)放入这些插槽中。每次升级都有单独的效果(例如,8 点火焰伤害或 10% 法力吸取)。因此,当您挥动剑时,它会造成基础伤害加上您添加的每次升级所增加的伤害。这与装饰器模式非常匹配。
【讨论】:
来自四人组:
例如,图形用户界面工具包应该允许您向任何用户界面组件添加边框等属性或滚动等行为。
...
装饰器符合它所装饰的组件的接口,因此它的存在对组件的客户端是透明的。装饰器将请求转发给组件,并且可能会在转发之前或之后执行其他操作(例如绘制边框)。透明度允许您递归嵌套装饰器,从而允许无限数量的附加职责。
【讨论】:
看看 Fowler 的描述;它给出了一个与书籍/视频相关的具体示例和一个“可借”的装饰器,你可以找到它here。
【讨论】:
我见过的最酷且最直接的用途之一是实现撤消能力,这可以追溯到单级撤消的糟糕时代。给定一个矢量绘图程序,选择了几个不同颜色的对象:执行一个命令来更改它们的所有颜色。并使其可撤销。这是通过应用一个装饰器来完成的,该装饰器在 getColor() 流中被调用,因此当它们被绘制时,它们被绘制成新的颜色;本质上,对象自己的 getColor() 方法被否决了。所以他们以新的颜色出现了。撤消就像从所有对象中删除装饰器一样简单;提交动作是将装饰器中的颜色应用到对象上,然后将其移除。比保存一张表格简单得多,其中列出了哪些对象已被着色以及它们的原始颜色是什么。
【讨论】:
装饰器模式的目的是:
动态地为对象附加额外的职责。装饰器为扩展功能提供了一种灵活的替代子类的方法。 [通过 Head First:设计模式]
装饰器模式最常用的是 GUI 和 java.io 类。 Head First: Design Patterns 有一个关于装饰器模式[link] 的免费章节,其中提供了一些其他示例:
我们将重新审视典型的过度使用 继承,你将学习如何 使用在运行时装饰你的类 对象组合的一种形式。为什么? 一旦你知道了技术 装饰,你可以给 你(或其他人)的新物品 不承担任何责任 底层代码更改 类。
您还可以阅读 Decorator Pattern by Example [PDF],其中在评估应用程序中使用了装饰器模式。
【讨论】:
您要求提供一个真实世界的示例,因此您可以:从 github 下载(或浏览)DonsProxy:
git://github.com/DonBranson/DonsProxy.git
DonsProxy 基本上使用 WireTap 模式让您监视或提取 HTTP 流量,此外它还允许您修改连接行为以模拟次优连接。我使用装饰器模式根据用户选项修改通道。命令行或 GUI 选项(取决于他们使用的视图)允许延迟注入和带宽注入等。当他们注入延迟时,这会将 LatencyDecorator 添加到通道中;如果他们限制带宽,则会将 ThrottleDecorator 添加到通道中。由于这使用了装饰器模式,因此他们可以根据自己的喜好混合搭配行为。
【讨论】:
如果您熟悉 Java 中的 Swing 开发(以及其他 GUI 工具包),您会发现装饰器模式被大量使用。你可能有一个构造函数,它接收一个特定的组件,然后向它添加功能。
【讨论】:
什么时候需要使用装饰器模式?
如果
使用Decorator_pattern如果可能,请给我一个非常适合该模式的真实示例。
我想出了我自己的自动售货机装饰器。
问题陈述:通过添加一种或多种口味(如糖、柠檬等)来计算饮料(茶或咖啡)的价格。
代码示例和解释可用@
【讨论】: