【问题标题】:Duck example for strategy pattern [duplicate]策略模式的鸭子示例
【发布时间】:2014-05-14 01:18:27
【问题描述】:

我正在阅读 Java 中的策略设计模式。问题设置如下

你有一个鸭子类和几种鸭子。您必须对鸭子的飞行和嘎嘎行为进行编码。您显然不能在每个鸭类方法中对飞行、非飞行行为进行编码,尤其是如果您有 100 种不同种类的鸭子。因此,您创建了一个名为FlyingBehaviorQuackingBehavior 的行为接口,并具有NonFlyingBehaviorFlyWithWingsBehaviorMuteQuackBehaviorSqueakQuackBehavior 之类的实现。然后将这些设置在不同类别的鸭子的字段中。这样你就可以将行为与鸭子联系起来。

我不明白为什么它必须通过组合来完成,而为什么不能通过继承来完成。为什么不能创建NonFlyingDuckFlyWithWingsDuckSqueakingDuckMuteQuackingDuck 等子类,然后实现fly()quack() 方法,然后为鸭子分配适当的行为。这是因为不支持多重继承。所以如果你有一只不会飞的、吱吱叫的鸭子,那么你不能同时扩展squeakingDuckNonFlyingDuck 或者是别的什么东西。有没有办法通过继承来做到这一点?

我感到有些困惑。座右铭是“优先组合胜过继承”。为什么呢?

有人能详细解释一下吗?

【问题讨论】:

  • 这是来自 Head First 设计模式吗?因为他们有一个类似的例子以及首选解决方案的所有原因。当我找到它时会放在这里。
  • 我想说...你读过整本书吗?他们在 Head First Design Patterns 中很好地解释了这一点
  • 它来自 Head Fist 设计模式。问题显然是多重继承。谢谢大家的帮助。
  • 在支持多重继承的语言中,这对继承来说是相当容易的,但是在像 Java 这样你只有一个超类的语言中,你必须开始对类做出一些随意的决定层次顺序。
  • 无论如何你都应该避免多重继承 - stackoverflow.com/questions/406081/…

标签: java design-patterns inheritance


【解决方案1】:

我不知道有什么深入的解释,但为什么在这种情况下不使用继承很容易。因为 Java 不支持多重继承。
想象一下,在创建了 4 个类(NonFlyingDuck FlyWithWingsDuck 或 SqueakingDuck、MuteQuackingDuck)之后,您需要添加另一个行为吗? (就像我不知道,CodingDuck)。好吧,您将以 8 个课程结束,每个 CodingDuckBehavior 2 个课程(有些鸭子知道如何做,有些则不知道)。但为什么要停在这里?您可能对每种行为都有多个实现,这会使继承变得不切实际。
如果您可以将手放在Head First Design Patterns 上,我发现他们的策略模式示例非常好(它为您提供了继承路径可能出错的示例)。

【讨论】:

  • 太棒了。所以问题是多重继承。刚想到
  • 是的,如果您对为什么没有多重继承感兴趣,请谷歌“java 钻石问题”,看看为什么存在接口 :)
【解决方案2】:

有很多原因,如already discussed at length

没有多重继承通常是其中之一,但与其他我强调保留封装的其他继承相比毫无意义:当你扩展一个类时,你正在破坏封装,并且你可能会修改它的基本行为,这会破坏Liskov substitution principle .

因此,通常组合优于继承,根据经验,如果您有疑问,通常最好是组合而不是扩展。

Here你有另一个很好的例子总结了一些原因。

【讨论】:

    【解决方案3】:

    如果您尝试使用继承,您最终会得到太多类型的 Duck,并且结构笨拙。你如何定义一种既会叫又会吹口哨并且只在海上飞翔的鸭子,以及另一种会吹口哨但不会叫叫并在陆地上飞翔的鸭子等等。

    客户想要的是能够创建一只鸭子,然后通过调用方法来定义它的特性。

    Duck mallard = new Duck();
    mallard.setQuacks(true);
    
    Duck teal = new Duck();
    teal.setQuacks(true);
    teal.setWhistles(true);
    

    然后他们可以根据输入数据动态构建这些对象,而不必事先对它们进行编码。

    显然,如果您愿意,您可以通过子类化来优化Duck。然后您可以使用工厂来构建它们:

    class SeaDuck extends Duck {
    }
    

    策略模式的本质是您将策略构建到代码中。

    public call () {
      // Encode the Strategy.
      if ( quacks ) {
        // Quack.
      }
      if ( whistles ) {
        // Whistle.
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多