Java 鸭子示例策略模式-头优先设计模式

Java 鸭子示例策略模式-头优先设计模式,java,php,design-patterns,Java,Php,Design Patterns,我想问一些关于这本书中的鸭子的例子,它让我感到困惑和矛盾 问题 结论 他说“当joe向duck超类添加新行为时,他也添加了不适合sume duck子类的行为。” 但在结论中,他添加了performFly()和performQuack()有什么不同,因为我认为它与相同,他还添加了不适合sume Duck子类的行为 **图片取自书头优先设计模式 **这个问题并不是说这本书不好,我认为这本书真的很好。正是我在问一些书中没有提到的问题。在结论中,他添加了两个新类,它们具有fly()函数。但是,该函数

我想问一些关于这本书中的鸭子的例子,它让我感到困惑和矛盾

  • 问题

  • 结论

  • 他说“当joe向duck超类添加新行为时,他也添加了不适合sume duck子类的行为。”

    但在结论中,他添加了
    performFly()
    performQuack()有什么不同,因为我认为它与
    相同,他还添加了不适合sume Duck子类的行为

    **图片取自书头优先设计模式
    **这个问题并不是说这本书不好,我认为这本书真的很好。正是我在问一些书中没有提到的问题。

    在结论中,他添加了两个新类,它们具有
    fly()
    函数。但是,该函数并不总是让鸭子飞起来。橡皮鸭不会飞,所以它们使用
    FlyNoWay
    类的实例。其他会飞的鸭子使用
    FlyWithWings
    类的实例。
    Duck
    类中的
    flyBehavior
    字段可能会在构造函数中设置

    函数
    performFly()
    将为选择的任何类调用
    fly()
    函数


    正如kainaw在评论中所说,这是一个相当复杂的解决方案。但是,它仍然可以使用。假设您正在创建一个鸭子设计程序。如果用户选择鸭子是否会飞,就不能硬编码。您可以创建布尔值,但可能需要处理更复杂的情况,如行为。您可能需要一个
    WildDuckBehavior
    类和一个
    DomesticDuckBehavior
    ,每个类都有自己的行为信息。基本上,这本书中的例子是如何使用它的简化版本。

    当你喜欢组合而不是继承时,策略模式就会起作用

    这是一个很好的实践,因为您可以在不必更改任何代码的情况下更改类的行为。你也不需要一个巨大的类树。您还可以动态更改类的行为

    它在示例中所做的是定义父类中的“行为”。在父类中定义鸭子可以有飞行行为和嘎嘎声行为。但这并不意味着孩子们的课堂必须有庸医或飞行

    你可以有一只不飞的鸭子,当你叫它“飞”的时候,它什么也不做,因为我们会有“不飞”的行为


    你可以随时改变鸭子的行为,而不是硬编码鸭子在类中所做的事情。

    我不是设计模式的大师,但当我读那本书时,我对那一章的第一感觉是界面的构建和实现方式,违反了众所周知的编程原则之一: 基本上,这一原则表明

    不应强制任何客户端依赖于它不使用的方法

    因为一些不飞的鸭子实现了fly()方法,即使它们不需要它。
    也就是说,我认为在这种特殊情况下,实现所有接口方法是不可避免的,因为在客户端,我们使用多态行为,我们需要确保所有方法都可用,即使没有使用

    你说得对。这本书提供的解决方案有一个巨大的问题: “FlyNoWay”不是“FlyBehavior”的子案例。要想有任何意义,飞行行为必须具备飞行能力。从中继承的类将指定行为(使用翅膀飞行等)。子类包含的类不能少于它从中继承的类

    仔细看,“FlyNoWay”只是一个伪类,它的引入是为了以一种不恰当的方式解决多态性问题

    正确的方法是使用接口

    class Duck
    {
        swim();
    }
    
    class MallardDuck : IFlyable
    {
        fly();
    }
    
    class RedheadDuck : IFlyable, IQuackable
    {
        fly();
        quack();
    }
    

    那么代码重用呢?您必须使接口尽可能严格,确保接口中的大多数更改都会导致程序无法编译。

    他们所做的只是使用一个函数(嘎嘎)并将其分离到一个单独的类中。这有点复杂。最好创建一个名为“FlyingDucks”的鸭子子类,然后将Fly()放在其中。然后,所有的飞鸭都将继承该类。或者,将FLy()抽象化,强制每个子类定义FLy的含义。他们所做的工作更多,也更复杂。每个子类都需要选择一个Fly类来分配给flyBehavior,即使它们不能飞行。如果我说
    问题
    结论是矛盾的,我说的对吗?或者我只是不明白他的意思?最好的设计是认识到,(虚构的)问题是考虑鸭子,橡皮鸭不是鸭子——它不会飞,不会游泳(除非你包括漂浮),等等。如果出于某种原因,你真的想有一个包含真正的鸭子和橡皮鸭的类,然后,你应该在你的问题空间中寻找这些项目的共同点,并使它们成为共同的属性;不要从空间中某些项目的公共属性开始,强制将其他项目与之匹配。需要注意的是,这是本书的第一章,他们本可以用于此解决方案的几个概念尚未介绍。很多时候,他们说“这可能是一个更好的方法,他们会在以后解决这个问题。”(意译)但橡胶鸭仍然继承了“飞”这个词,即
    橡胶鸭
    不需要它吗?@MuhammadRifkiMockie我稍微看错了图表,所以我编辑了答案。这有用吗?