0

I've been using this tutorial to look into the Strategy pattern. I receive the output he talks about, but it seems like there is no option to use the digHole() method. When I call the method in the Dog() constructor it works though.

My guess is this happens because I need to implement a way to save the ability to dig in the Animal class (like the flying ability), am I correct in this? Does this also mean that for every action I want an animal to take, I should compose it in the Animal class, create an interface with the ability and then create two classes who implement that ability, meaning the ability is either implemented or it isn't?

I also have some troubles with formulating the main thought behind the Strategy pattern. Currently I'm looking at it as 'Encapsulate all actions and compose them together in one main class'. How accurate/fitting is this?

public class Animal {

    public Flies flyingType;

    public String tryToFly() {
        return flyingType.fly();
    }

    public void setFlyingAbility(Flies newFlyType) {
        flyingType = newFlyType;
    }
}


public class Dog extends Animal {

    public Dog() {
        super();
        setSound("Bark");
        flyingType = new CantFly();
    }

    public void digHole() {
        System.out.println("Dug a hole");
    }
}


public interface Flies {

    String fly();

}

class ItFlies implements Flies {

    public String fly() {
        return "Flying high";
    }

}
class CantFly implements Flies {

    public String fly() {
        return "I can't fly";
    }

}
Jeff
  • 12,555
  • 5
  • 33
  • 60
Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170

3 Answers3

2

I also have some troubles with formulating the main thought behind the Strategy pattern

Perhaps the best way to wrap your head around the Strategy pattern is to compare it to the Template method. Click on the links for the wikipedia articles.

Both involve certain design decisions up front in the base class, but when it finally gets down to specifying the different behavior for the various subclasses, the template pattern relies on inheritance - overriding an abstract method defined in a base/super class.

The strategy pattern relies on composition - the behavior (flying, digging) is itself an object which can be created independently and then injected into object of interest.

In a language like Java, once you override a method in the base class and then create an instance of the object, that behavior can never be changed. If that's how you want your object to work - great use inheritance. However if you don't know until runtime which behavior you will need, then it's worth the extra effort to design using the strategy pattern.

meaning the ability is either implemented or it isn't?

Although the tutorial you are referencing is rather clever, it's not a great model for using the strategy pattern. Adding the ability of flying to a dog is so counter-intuitive that it distracts from the lesson. With the strategy pattern there is no limit to the number of possible implementations of the algorithm of interest.

If you really want to stick with the Animal model, you might try more universal concepts like findFood, escapeFromPredator, findMate, raiseYoung - things which are meaningful to all animals but are not going to be exactly the same for every animal instance. Two different dog's might raiseYoung quite differently or do so differently over time so the strategy may need to be swapped out as the animal simulation continues.

Do I have to compose every method in my main class

You can, but you do not have to if it gets too tedious - to simplify usage of your classes you can have each object instantiate an appropriate strategy in it's own constructor. Then you have your choice - create the object and use the default behavior or replace the default behavior with another depending on the application.

Guido Simone
  • 7,912
  • 2
  • 19
  • 21
0

Just create abstract method in Animal, so the Animal class become abstract too, but we don't care because what's is an animal in general, that's had no sense. And in each class who inherits Animal define an implementation of this method.

This is not the pattern strategy, but I think it's one of the good way to do what you want (like I understood it)

Guillaume
  • 8,741
  • 11
  • 49
  • 62
  • In the video he explicitly said to avoid having to implement the method in every class of a type of animal because of the code duplication. I'm not trying to solve a real-world problem, I'm merely trying to understand the mechanics of the Strategy pattern. – Jeroen Vannevel Dec 10 '12 at 22:06
0

The idea of the pattern strategy as I understand it is that the subclasses define the same kind of behaviour in different ways.

So if you have a hundred kinds of animals, and some of them can only fly, some of them can only dig and some can do both, you have both fly and digHole as methods on the superclass.

It's not about composing all of the behaviour into the superclass, though - if only dogs can dig, and it doesn't even make sense for animals in general, then it doesn't make sense for you to put digHole into Animal - when you want a dog to dig, you probably should know whether or not it is a Dog anyway, or if you want to move from Animal to Dog (for instance to get all of the dogs out of an Animal list) so that you can use the digHole method, you can use an explicit cast

Jeff
  • 12,555
  • 5
  • 33
  • 60
  • That's indeed what I was unclear about. However considering only dogs can dig a hole, what do I have to change so I would be able to make a dog dig a hole from the main class? As of right now, this isn't possible. I was under the impression that `Animal sparky = new Dog(); sparky.digHole();` should work when executed in the main method. However when you do that, an exception appears saying digHole() isn't implemented in Animal. So should I implement it there anyway, even though it is dog-only. – Jeroen Vannevel Dec 10 '12 at 22:44
  • No. If you don't want to change the type of the `sparky` variable, use `((Dog)(sparky)).digHole()` - that's an explicit cast that tells the compiler that actually `sparky` *is* a dog - otherwise as far as the compiler knows it could be a cat or a bird or a diglett – Jeff Dec 10 '12 at 22:49