I'm revisiting the first chapter from Head First Design Patterns, which is my favorite one so far.
It promotes the composition against inheritance through the strategy pattern, and to put it together, here are the main points of the two approaches as I got from the chapter.
Choosing full inheritance (no polymorphism) may be good if you are looking for
- Code reuse: Code can be written once and shared among subclasses.
but you should think twice before using inheritance for only that purpose because, on the other hand, this can be at a cost, because:
- Every subclass will share the "default" behavior, with no possible customization, classes lose the singularity advantage.
The first solution that comes to mind is employing polymorphism through using interfaces or abstract classes, that fixes the full inheritance issue so:
Behavior can be customized (any subclass can have its own version of the base class/ interface).
But here are the issue with polymorphism:
- Change is costly, where you have to go through all implementations to change the behavior.
- There may be duplications.
So the strategy pattern comes into play if you want to avoid the red points.
The problem is that you don't know if your implementation needs full inheritance or be overridable. because when inheriting implementation from the base class you're stating strongly, that the subclass will never change in a different direction, and when using polymorphism you're stating that the subclass will always be different than the base class, the problem is that; you're always referencing the base class in a way or another: changes are done with respect to the base class.
In the strategy pattern behaviors of subclasses have their own personality that shouldn't be tied to the base class(1), and you compose them into the subclasses and you can change this behavior in runtime.
Let us have the example used in the HFDP book:
you want to implement different types of ducks in the app, each with fly and quack behaviors,
so here's is the IFlyBehavior
public interface IFlyBehavior { void Fly(); }
public interface IQuackBehavior { void MakeQuack(); }
public abstract class Duck { public void Display() { Console.WriteLine($"{Name} Duck"); } public IFlyBehavior flyBehavior; public IQuackBehavior quackBehavior; public abstract string Name { get; } public void Fly() { flyBehavior.Fly(); } public void Quack() { quackBehavior.MakeQuack(); } }
public class DecoyDuck : Duck { public DecoyDuck() { flyBehavior = new FlyNoWay(Name); quackBehavior = new MuteQuack(Name); } public override string Name => "Decoy"; }
flyBehavior = new FlyNoWay(Name); quackBehavior = new MuteQuack(Name);
var duck = new DecoyDuck(); duck.SetFlyBehavior(new FlyNoWay("Decoy"))
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.