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";
}
}
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.