
Motivation
Problem: Started with a simple SimUDuck App.
- Joe’s company makes a duck pond simulation game, SimUDuck, The game can show a large variety of duck species swimming and making quacking sounds.

But now we need the ducks to FLY

First Design:
- Joe add a method
fly()into the Duck class. It seem to work, but something went horribly wrong because not all ducks can fly.

What we got, Rubber ducks are also able to fly


Drawbacks
- A localized update to the code caused a nonlocal side effect (flying rubber ducks)!

Second Design:
Using inheritance and polymorphism
- Always override the
fly()method in the subclass where needed.

Drawbacks:
- Joe realized that inheritance probably wasn’t the answer, because he just got a memo that says that the executives now want to update the product every six months (in ways they haven’t yet decided on). Joe knows the spec will keep changing and he’ll be forced to look at and possibly override
fly()andquack()for every new Duck subclass that’s ever added to the program… forever - Everytime a new duck is added, you will be forced to look at and possibly override
fly()andquack(). - So is there a cleaner way of having only some of the duck types fly or quack?
Third Idea
How about an interface?


Drawbacks: It completely destroy code reuse for those behaviors.

Why this will not work?
- Only the ducks that are supposed to fly will implement that interface and have a
fly()method. - When you need to make a little change to the flying behavior, we will need to change in all the subclasses.
Conclusions:
- We know that not all of the subclasses should have flying or quacking behavior, so inheritance isn’t the right answer. So we know using inheritance hasn’t worked out very well, since the duck behavior keeps changing across the subclasses, and it’s not appropriate for all subclasses to have those behaviors.
- While having the subclasses implement Flyable and/or Quackable solves part of the problem (no inappropriately flying rubber ducks), it completely destroys code reuse for those behaviors, so it just creates a different maintenance nightmare. The Flyable and Quackable interface sounded promising at first—only ducks that really do fly will be Flyable, etc. — except Java interfaces have no implementation code, so no code reuse. And that means that whenever you need to modify a behavior, you’re forced to track down and change it in all the different subclasses where that behavior is defined, probably introducing new bugs along the way!
Solution
- Design Principles: Identify the aspects of your application that vary and separate them form what stays the same! which means Encapsulate the parts that vary!
- Design Principles: Program to an interface, not an implementation! (interface here means supertype! including interface and abstract class!.. making use of the polymorphism functionality).
- Design Principles: Favor composition over interface!
- We know that not all of the subclasses should have flying or quacking behavior, so inheritance isn’t the right answer.
- But while having the subclasses implement Flyable and/or Quackable solves part of the problem (no inappropriately flying rubber ducks), it completely destroys code reuse for those behaviors, so it just creates a different maintenance nightmare.
- And of course there might be more than one kind of flying behavior even among the ducks that do fly…
Strategy Pattern



Final UML Diagram

Ref:
- https://www.oreilly.com/library/view/head-first-design/0596007124/ch01.html
- https://www.freecodecamp.org/news/the-strategy-pattern-explained-using-java-bc30542204e0/
TODO:
- https://faun.pub/head-first-design-patterns-using-go-1-welcome-to-design-patterns-the-strategy-pattern-6cbd940e113a
- Check the code mentioned in https://github.com/bethrobson/Head-First-Design-Patterns/tree/master/src/headfirst/designpatterns/strategy