Reputation: 33
In most of the design patterns concepts, it was mentioned that "Has A" is better than "Is A" means.
In the first chapter - Head First Design Patterns - "Intro to Design Patterns", section "Integrating the Duck Behaviour" (page no 15), the Duck class is having references to FlyBehavior and QuackBehavior interface types. For example, we are going to add a new behavior in feature name it XYZBehavior (just assume client has not yet decided it) for one kind of Ducks, we need to change the Duck class to have the reference to new interface. Resulting, we need to alter the class but which should not happen according to good design pattern.
Can you suggest me how can we deal with this requirement?
Upvotes: 3
Views: 194
Reputation: 38910
You can handle this scenario by using Composition
=> Duck
has a list of Behaviours
.
Duck
will maintain a list of Behaviour objects. Populate relevant behaviours during creation of Duck
object.
Sample code:
import java.util.*;
interface Behaviour{
}
class FlyBehaviour implements Behaviour{
}
class QuackBehaviour implements Behaviour{
}
class XYZBehaviour implements Behaviour{
}
public class Duck{
private List<Behaviour> duckBehaviours = new ArrayList<Behaviour>();
public Duck(List<Behaviour> list){
duckBehaviours = list;
}
public static void main(String[] args){
// set the behaviours
List<Behaviour> list = new ArrayList<Behaviour>();
list.add(new FlyBehaviour());
list.add(new QuackBehaviour());
list.add(new XYZBehaviour());
Duck duck = new Duck(list);
}
}
Upvotes: 0
Reputation: 114787
The Strategy pattern does not prevent from changing the class if you add a new behaviour (strategy). It just prevents from touching the class, if an existing behaviour (strategy) changes.
Example with QuackBehaviour: assume, we thought, a duck would sound like "quaack" but after some years of research we realised, that ducks actually sound like "quaaack". We're lucky, we implemented a QuackBehaviour and just adjust the implemtation of the QuackBehaviour interface for common ducks. That's the trick with this pattern.
If later on, we decide to add a SwimBehaviour, because another research team realized, that swimming is a common duck behaviour, then we have to touch the common duck and add that behaviour (to the Duck
class).
Hope it helped!
Upvotes: 0
Reputation: 298938
That problem can be solved by using Dependency Injection
(In Java usually through either Spring or Guice)
Here's a Beginner's Guide to dependency Injection
Basically, a Bird would have a behaviors property:
private Collection<Behavior> behaviors;
public void setBehaviors(Collection<Behavior> behaviors){
this.behaviors = behaviors;
}
Now in a Configuration file you would specify which Behaviors get injected into the Bird without having to change the Bird class.
Upvotes: 1