I'm trying to implement the strategy pattern in my code but I've run into something not covered in the examples I've seen. And that is when a strategy needs to reference a method contained in the parent class.
For the simple example (without a parent ref), lets use the Duck and QuackBehaviour example:
class RubberDuck extends Duck {
public RubberDuck() {
setQuackBehaviour(new Squeak());
}
}
class Squeak implements QuackBehaviour {
public String quack() {
return "QUACK!";
}
}
But what if we now have a duck that likes to say its own name? That would mean QuackBehaviour needs some sort of reference to the duck itself.
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(this));
}
}
class SayName implements QuackBehaviour {
private Duck duck;
public SayName(Duck duck) {
this.duck = duck;
}
public String quack() {
return duck.getName();
}
}
This smells like bad code to me. Is this an anti-pattern? It prevents QuackBehaviour from being reused by a non-Duck object. And something about the co-dependency between the classes doesn't sit well with me.
I guess you could also pass in a Function to PsyDuck like:
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(() => this.getName()));
}
}
But if we start requiring multiple fields from the behaviour, then we would have to pass in many function arguments.
Or is it best to have SayName be an abstract class and have PsyDuck implement a concrete version?
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new PsyDuckSayName());
}
class PsyDuckSayName extends SayName {
protected String getName() {
return PsyDuck.this.getName();
}
}
}
abstract class SayName implements QuackBehaviour {
public String quack() {
return getName();
}
protected abstract String getName();
}
The last approach seems the cleanest, but I would love some feedback and advice.