Question

I'm currently reading 'Head first design patterns' and I already have a few questions on the first chapter of the book. This chapter introduces the 'prefer composition over inheritance' design principle, by explaining the 'Strategy-Pattern'. My question isn't about the pattern, but rather about a more basic design decision in one of the examples:

There is an abstract Duck class, from which a hand full of other duck classes (like e.g. 'Rubber-' or 'Redhead-Duck') inherit. All of these ducks have a display and quack method. The display method is what should be differernt in every special duck class (because every duck looks different, as the book says).

abstract class Duck
{
    public void display();
    public void quack()
    {
        //Quack here
    }
}

class RubberDuck extends Duck
{
    @Override
    public void display()
    {
        //Display a 'Rubber-Duck'
    }
}

class RedheadDuck extends Duck
{
    @Override
    public void display()
    {
        //Display a 'Redhead-Duck'
    }
}

But my question is: Wouldn't it make much more sense to have a field inside a (non-abstract) Duck class, which contains the displaying information (a picture or a 3D-model for example) rather than inheriting from an abstract duck class?

class Duck
{
    private String duckName;
    private Picture duckPicture;

    public Duck(String name, Picture picture)
    {
        this.duckName = name;
        this.duckPicture = picture;
    }

    public void quack()
    {
        //Quack here
    }
    public void display()
    {
        //Show duck here, according to the 'duckPicture' field
    }

    //More methods here, maybe a getter for the 'duckName' field
}

What's your opinion on this? Does it make sense to have an abstract duck class and inherit from it or do you prefer the second solution?

Était-ce utile?

La solution

You have to understand that examples are almost always oversimplified to such an extent that techniques like inheritance look like overkill.

If the real-world code were of a similar complexity as the Duck hierarchy, with each class only differing in which picture/text they show, then you would have a case.

But in reality, the real-world code is much more complex, usually with at least a handful of methods that have radically different implementations across the classes. In that case, it doesn't work anymore to catch the variation in a few fields.

Autres conseils

If you assume that display operation will only send rasterized image to display device, then you are right - one implementation of display method would suffice.

But, if you have an abstract method for display operation, this method can also do some implementation-specific stuff like:

  • create the image of a duck using openGL API,
  • update other fields of a duck (e.g. isDisplayed),
  • call Display on sub-objects (e.g. DuckWing),
  • etc.
Licencié sous: CC-BY-SA avec attribution
scroll top