"鸭子策略模式"示例
"鸭子策略模式"示例
这个问题已经有了答案:
我在阅读Java中的策略设计模式。问题如下所述:
你有一个鸭子类和多种类型的鸭子。你必须编写鸭子的飞行和叫声行为。显然,你不能在每个鸭子类方法中编写每种鸭子的飞行和非飞行行为,特别是如果你有像100种不同种类的鸭子。所以你创建了一个名为FlyingBehavior
和QuackingBehavior
的行为接口,然后有如NonFlyingBehavior
或FlyWithWingsBehavior
或MuteQuackBehavior
或SqueakQuackBehavior
的实现。然后把这些设置为不同鸭子类中的字段。这样你就能将行为关联到鸭子上。
我不明白的是为什么必须使用组合而不是继承。为什么不能创建像NonFlyingDuck
,FlyWithWingsDuck
、SqueakingDuck
、MuteQuackingDuck
等子类,然后实现fly()
或quack()
方法,再为鸭子分配适当的行为。这是因为不支持多继承吗?如果你有一个不会飞且发出吱吱声的鸭子,那么你不能同时扩展SqueakingDuck
和NonFlyingDuck
,或者是其他原因吗?使用继承存在某种方法吗?
我感到有点困惑。座右铭是“组合优于继承”。为什么呢?
有人能深入解释一下吗?
有许多原因,如已经广泛讨论过。
不支持多重继承通常是其中之一,但与其他原因相比意义不大,我要强调保留封装性:当你继承一个类时,你正在破坏封装性,你会有风险修改它的基本行为,这会违反Liskov替换原则。
所以,通常情况下,首选组合而非继承,而且一个经验法则是如果你不确定,通常情况下使用组合而非继承更好。
在这里,你有另一个总结一些原因的好例子。
我不知道关于这个深入解释,但为什么在这种情况下不使用继承很容易。因为Java不支持多重继承。
想象一下,在创建了非飞行鸭子FlyWithWingsDuck或吱吱作响鸭子MuteQuackingDuck之后,您需要添加另一个行为时?(就像我不知道,小鸭子CodingDuck)。那么您将得到8种类,每种CodingDuckBehavior都有两种(有些鸭子知道如何,有些鸭子不知道)。但为什么要停在这里呢?您可能拥有每个行为的多个实现,这使继承变得不切实际。
如果您可以获取Head First 设计模式,我发现它们的策略模式示例非常好思考(它还提供了继承路径可能出错的示例)。