Duck example strategy pattern - Head first design pattern

前端 未结 4 1436
鱼传尺愫
鱼传尺愫 2020-12-16 22:01

I want to ask something about duck example on this book that made me confused and I feel contradictions.

  1. Problem

相关标签:
4条回答
  • 2020-12-16 22:33

    In the conclusion, he is adding two new classes that have a fly() function. However, the function does not always make the duck fly. Rubber ducks can't fly, so they use an instance of the FlyNoWay class. Other ducks that can fly use an instance of the FlyWithWings class. The field flyBehavior in the Duck class would probably be set in the constructor.

    The function performFly() would call the fly() function for whatever class is chosen.

    As stated by kainaw in the comments, this is a rather complicated solution. However, it can still be used. Say that you are creating a duck designing program. If the user chooses whether the duck can fly, it can't be hard coded. You could create a Boolean value, but you might need to handle more complicated situations like behavior. You might need a WildDuckBehavior class and a DomesticDuckBehavior, each with its own information about how to act. Basically, the example in the book is a simplified version of how this would be used.

    0 讨论(0)
  • 2020-12-16 22:42

    The strategy pattern works when you favor composition over inheritance http://en.wikipedia.org/wiki/Composition_over_inheritance

    This is a good practice because you can change the behavior of a class without having to change any code. And you don't need a huge tree of classes either. You also can change the behavior of a class dynamically.

    What it does in the example is that defines "behaviors" in the parent class. In the parent class you define that a Duck can have a flying behavior and a quacking behavior. But it doesn't mean the children classes have to have quack or fly.

    You can have a nonflying duck and when you call "fly" it will do nothing because we'll have a "non-flying" behavior.

    Instead of hardcoding what a duck does in the class, you can change the behavior of this duck whenever you want.

    0 讨论(0)
  • 2020-12-16 22:44

    I'm not a guru of design patterns, but while I was reading that book, the first sensation I had about that particular chapter was that the way interfaces was built and then implemented, violated one of the well know programming principle: the Interface Segregation Principle (ISP) Basically this principle state that

    no client should be forced to depend on methods it does not use

    Because some Ducks that don't fly implement the fly() method even it they don't need it. That said, I think that in this particular case it is unavoidable to implement all the interfaces methods since on the client side we're using polymorphic behaviors, and we need to be sure that we have all the methods available even if unused.

    0 讨论(0)
  • 2020-12-16 22:48

    You're correct. The solution offered by the book suffers from one huge problem: "FlyNoWay" is not a sub case of "FlyBehaviour". To have any meaning, FlyBehaviour must require the ability to fly. Classes that inherit from it will specify the behaviour (fly using wings etc.). A sub class cannot contain less than the class it inherits from.

    Taking a closer look, "FlyNoWay" is just a pseudo class that was introduced to solve the problem of polymorphism in an inappropriate way.

    The right method is to use interfaces.

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

    What about code reuse? Well you have to make the interface as strict as possible, assuring that most changes in the interface will cause the program to not compile.

    0 讨论(0)
提交回复
热议问题