何时需要使用装饰器模式?如果可能的话,给我一个非常适合该模式的真实世界示例。
答案 0 :(得分:51)
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似乎有免费的装饰章节,装饰模式。 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工具包),您将看到装饰器模式经常使用。您可能有一个构造函数接受特定组件,然后向其添加功能。