我们什么时候需要装饰模式?

时间:2010-08-13 14:44:46

标签: design-patterns decorator

何时需要使用装饰器模式?如果可能的话,给我一个非常适合该模式的真实世界示例。

8 个答案:

答案 0 :(得分:51)

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似乎有免费的装饰章节,装饰模式。 Google出现了这个链接: PDF

答案 1 :(得分:20)

两个现实生活中的例子:

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

答案 2 :(得分:8)

来自四人帮:

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

...

  

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

答案 3 :(得分:5)

看看福勒的描述;它提供了一个关于书籍/视频和装饰“可借”的具体例子,你可以找到它here

答案 4 :(得分:3)

Decorator模式的目的是:

  

动态地将附加职责附加到对象。装饰器为子类化提供了灵活的替代扩展功能。 [via Head First:Design Patterns ]

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

  

我们将重新检查典型的过度使用情况   继承,你会学习如何   使用在运行时装饰您的类   一种形式的对象组合。为什么?   一旦你了解了技术   装饰,你将能够给予   你的(或别人的)对象是新的   没有任何责任的责任   代码更改为底层   类。

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

答案 5 :(得分:3)

我所见过的最酷和最文字的用途之一就是实现撤销能力,回到单级撤销的糟糕时代。给定一个矢量绘图程序,选择几个不同颜色的对象:实现一个命令来改变它们的所有颜色。并使其可以撤销。这是通过应用一个在getColor()流中调用的Decorator来完成的,这样当它们被绘制时,它们就会被绘制成新的颜色;本质上,对象自己的getColor()方法被否决了。所以他们出现了新的颜色。撤消就像从所有对象中删除Decorator一样简单;提交动作是将装饰器中的颜色应用到对象然后将其删除。比保持一张桌子上的物体已被着色以及它们的原始颜色更为简单。

答案 6 :(得分:2)

你问过一个真实世界的例子,所以你去:从github下载(或浏览)DonsProxy

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

DonsProxy基本上使用WireTap模式来让您观看或提取HTTP流量,此外,它还允许您修改连接行为以模拟次优连接。我使用Decorator模式根据用户选项修改通道。命令行或GUI选项(依赖于他们正在使用的View)允许延迟注入和带宽注入等。当他们注入延迟时,会将LatencyDecorator添加到频道;如果他们限制带宽,则将ThrottleDecorator添加到频道。由于这使用了装饰器模式,因此它们可以根据心脏的内容进行混合和匹配。

答案 7 :(得分:1)

如果您熟悉Java中的Swing开发(以及其他GUI工具包),您将看到装饰器模式经常使用。您可能有一个构造函数接受特定组件,然后向其添加功能。

这是a good article that uses Swing as an example