有人可以告诉我使用构造函数注入另一个类而不是类继承来创建装饰器类之间的区别(如好处)吗?在我能想到的例子中,我可能会以两种方式中的一种来实现相同的最终目标,但我怀疑我错过了一些基本的东西。
3 回答
装饰器模式涉及组合对象。为了能够继承该对象的类型,它显然必须是可继承的。并非所有类型都是为继承而设计的,也就是说,它们都是基类,即使从纯粹的技术角度来看它们可以被继承(我认为这是一个设计缺陷)。
装饰器模式存在的理由是能够在不修改对象本身的情况下修改对象的行为。通过继承,您实际上是在修改对象本身,然后您得到的是通过多态性进行的常规行为变化,这意味着您没有完成相同的事情。
因此,装饰和继承都有其用途。当其中任何一个为真时使用装饰
- 您不能继承(例如,如果该类
sealed
在 C# 中) - 你不应该继承(该类显然不是基类)
- 你想多次改变一个特定对象的行为(通过用不同行为的装饰器包装它)
请注意,继承是 OO 工具箱中最强大的工具。强大的力量伴随着巨大的责任,而这并不总是容易应付的。我会说:总是组合或聚合。当这无法完成时,继承。如果你不能继承,那就更努力地组合或聚合。”
我将恢复如下:
你应该什么时候继承?
当对象来自相同的语义层次并表示is-a关系时。
那是什么意思?
那 a Cat
is-a Feline
,确实 a Feline
is-a Vertebrate
,等等。
你应该什么时候装修?
当对象不代表is-a关系时。但是,是的,两者Coffee
和Milk
都可以在同一个层次结构中。但如果你要卖Cappuccino
,你不会说咖啡是牛奶,而是用Milk
.
结论:
Is-a与has-a不同。一个是子类型,另一个是组合的一部分。
但是,请参阅:https ://stackoverflow.com/questions/1621344/head-first-design-patterns-decorator-pattern
一个真实的例子是为您的控制器或服务创建一个安全容器作为装饰器,以便进行 ACL 检查。
装饰的另一个非常好的理由是它为您提供了装饰接口而不是类的选项。然后你变得非常松散耦合,并且可以将正交装饰行为添加到接口的多个实现中,而无需编写更多代码。