oym*_*oym 32 java oop design-patterns decorator
这个问题被问已经在这里,但不是回答具体问题,的装饰图案作品是如何给予,而不是描述.我想再次提出这个问题,因为通过阅读装饰器模式的工作方式,我的答案并不是很明显(我已经阅读了维基百科的文章和Head First Design Patterns一书中的部分).
基本上,我想知道为什么必须创建一个实现(或扩展)某个接口(或抽象类)的抽象装饰器类.为什么所有新的"装饰类"都不能简单地实现(或扩展)基本抽象对象本身(而不是扩展抽象装饰类)?
为了使这个更具体,我将使用设计模式书中处理咖啡饮料的例子:
Beverage
HouseBlend
简单的延伸Beverage
CondimentDecorator
创建了一个扩展Beverage
并具有实例的抽象类Beverage
Milk
创建一个扩展的类CondimentDecorator
我想理解为什么我们需要这个CondimentDecorator
类,以及为什么类Milk
不能简单地扩展Beverage
类本身并Beverage
在其构造函数中传递一个实例.
希望这很清楚...... 如果不是,我只想知道为什么这个模式需要抽象装饰器类?谢谢.
编辑:我试图实现这一点,省略了抽象装饰器类,它似乎仍然有效.这个抽象类是否存在于此模式的所有描述中,仅仅因为它为所有新装饰类提供了标准接口?
Mik*_*kis 31
迟到一年半比没有好:
某个接口的装饰器的基类不是必需的,但是它非常有用.
它是有用的,一方面作为一种记录方法,从它派生的类是有问题的接口的装饰器,但主要是因为装饰器通常不需要为装饰接口的每个方法添加功能,所以一个基础装饰器类允许派生装饰器只实现它们实际需要添加某些功能的接口的那些方法,将其余的方法留给基类来提供默认实现.(只是简单地将呼叫委托给死者.)
将此与从头开始实现装饰接口的编写装饰器进行对比,其中编译器要求您为接口的每个单独方法提供实现,无论装饰器是否将向其添加任何功能.
这很简单,真的.
Raf*_*afa 11
(你的问题有点晚了..)
我也花了很长时间试图找出答案.在我的例子中,非具体的Decorator扩展了要装饰的类("decoree"),而不是decoree和Decorator共有的接口.
从不同来源阅读后,在我看来,除了tvanfosson所说的,让混凝土装饰器扩展一个抽象或更一般的装饰器的原因是我们不会一遍又一遍地重复"委托"代码.
[Beverage]<———————[(abstract) CondimentDecorator]<—————[Milk]
[decoree ]——————<>[ adds code to efficiently ]
[ forward calls to decorated ]<—————[LemonJuice]
[ instance of Beverage ]
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您的抽象装饰器将扩展decoree并实现与decoree相同的接口,委托/转发所有方法调用.然后,你可以构建的具体装饰器只需要实现那些你想要做一些不同的方法,而不仅仅是将方法调用转发给decoree.
我希望我很清楚......: - S
就个人而言,我对在装饰器中重复decoree界面的需要感到有点失望.这增加了一些耦合,因为在decoree的界面发生变化的任何时候(比如获得更多方法),装饰者需要赶上.
在PHP 5.3.2中(是的,我知道你的问题与Java有关),但是,应该可以动态捕获所有方法调用并将它们全部转发,而不需要Decorator需要知道调用哪些方法(在但是,这是一种非常有效的方法,必须使用Reflection API).我想这已经可以在Ruby和其他语言中实现.
PS:这是我在SO中的第一个回答!^ _ ^
Jer*_*emy 11
我想知道同样的事情.回到源代码,GOF设计模式,我在装饰器章节的"实现"中看到了这一点:
"省略抽象的装饰类,没有必要定义一个抽象的装饰类时,你只需要添加一个责任,这是经常发生的情况,当你处理现有的类层次结构,而不是设计一个新的.在这种情况下,您可以将Decorator的责任合并到将组件的请求转发到Concrete Decorator中."
所以至少在这种情况下,似乎GOF同意你:-)
我不确定"一个责任"的含义是什么.我不知道,如果超过"一个责任"意味着有一个以上的责任或一个以上的混凝土装饰混凝土一个装饰,每一个都有一个责任.无论哪种方式,我都不明白为什么抽象的装饰器是必要的.我的猜测是,tvanfosson的回答(在他自己的答案评论)是正确的 - 一旦你开始创建一些装饰类的,它澄清超类的设计之下决定将它们分组.在另一方面,如果只有一个班,这或许使得设计决策不太清楚,如果你只是坐在作为基础元件和装饰(之间无谓的中间人第二类话说回来,这是相当有可能增加你想要在某些时候添加更多,
无论如何,似乎与设计清晰有关,而不是代码工作与否之间的区别.
它可以使用不同组合的各种装饰器独立地装饰基类,而不必为每种可能的组合派生类.例如,假设你想要Beverage
牛奶和肉豆蔻.使用基于抽象装饰器类的装饰器,你只需用with Milk
和Nutmeg
decorators 包装.如果它来自Beverage
,你必须有一个MilkWithNutmegBeverage
类,一个MilkBeverage
类和一个NutmegBeverage
类.您可以想象随着可能组合的数量增加,这会如何爆炸.使用抽象装饰器实现将每个装饰减少到一个装饰器类实现.
基础装饰器可以更轻松地创建其他装饰器。想象一下,Beverage 有几十个抽象方法,或者是一个接口,比如stir()、getTemperature()、drink()、pour() 等。然后你的装饰者都必须实现这些方法,只是为了将它们委托给包装好的饮料,并且你的 MilkyBeverage 和 SpicyBeverage 都拥有所有这些方法。
相反,如果您有一个具体的 BeverageDecorator 类,它通过简单地将每次调用委托给包装的 Beverage 来扩展或实现 Beverage,则子类可以扩展 BeverageDecorator 并仅实现它们关心的方法,而让基类来处理委托。
如果 Beverage 类(或接口)获得新的抽象方法,这也可以保护您:您需要做的就是将该方法添加到 BeverageDecorator 类。没有它,您将不得不将该方法添加到您创建的每个装饰器中。
归档时间: |
|
查看次数: |
9530 次 |
最近记录: |