Please check each branches for stepwise implementation of the code
- step 1 - branch step1
- step 2 - branch step2
- step 3 - branch step3
- step 4 - branch step4
- Super Class
- Duck
- Sub Classes
- MallardDuck
- RedHeadDuck
- RubberDuck
- Mallard Duck
- RedHead Duck
- Rubber Duck
- Similar to the previous design
- Mallard Duck
- RedHead Duck
- Rubber Duck
- Super Class
- Duck
- Sub Classes
- MallardDuck
- RedHeadDuck
- RubberDuck
- DecoyDuck
- Interfaces
- Flyable
- Quackable
- Mallard Duck
- RedHead Duck
- Rubber Duck
- Decoy Duck
- Super Class
- Duck
- Sub Classes
- MallardDuck
- RedHeadDuck
- RubberDuck
- DecoyDuck
- Interfaces
- FlyBehavior
- QuackBehavior
- Behavior Classes
- FlyBehavior
- FlyWithWings
- FlyNoWay
- QuackBehavior
- Quack
- Squeak
- MuteQuack
- FlyBehavior
- Mallard Duck
- RedHead Duck
- Rubber Duck
- Decoy Duck
- It allows to encapsulate the behaviors as a family of algorithms
into their own set of class - Also allows to change the behavior at runtime
The Strategy Pattern defines a family of algorithms, encapsulate each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
This is the same scenario used in the "Head First Design Patterns" book.
Please refer the SimDuck app section for details description of the scenario.
Duck class
MallardDuck class
RedHeadDuck class
RubberDuck class
App class
Step 1 Output
As you can see it is not ideal fro rubber duck to fly. When adding the flying behavior to the ducks supper class the programmer failed to identify that it is was not appropriate for some duck subclasses. *A localized update to the code caused a non-local side effect (flying rubber ducks)
Override the fly() method in the RubberDuck class to do nothing
RubberDuck class
Step 2 Output
What happens when a wooden decoy duck added to the programme?.
Override the fly(), swim(), quack(), method in the DecoyDuck class to do nothing. But what happens when new types of duck (like rubber duck, decoy duck) adds to the system quit frequently. Then we'd have an overwhelming task in our hands to override every method fro each new class. So the Inheritance (concept of OOP) is not really the way to go. We now need a cleaner way to have only some(but not all) of the duck types fly or quack.
A better solution here would be to use interfaces.
Duck class
MallardDuck class
RedHeadDuck class
RubberDuck class
DecoyDuck class
Flyable interface
Quackable interface
App class
Step 3 Output
An additional add method is used here because if the encapsulation. Now what let's say we need to make a little change in flying behavior. We have to go through all the flying duck subclass. This completely destroys the code reusing concept (Lot of duplication).
Identify the aspects of your application that vary and separate them from what stays the same.
Take what varies and "encapsulate" it so it won't affect the rest of the code. later you can alter or extend the parts that vary without affecting those that don't.
According to the 1st design principle we can identify the parts that vary like this
program to an interface, not an implementation.
from now on duck behaviors will live in a separate class, which implements a particular behavior interface. Now duck class won't need to know any implementation details of it's own behaviors.
This time, Duck class is not the one who will implement these interfaces/behaviors
Note: When we say program to an interface, it's actually program to a supertype. (abstract class or interface). The point is to find polymorphism by programing to a super type, so that actual runtime object isn't lock into the code. In simple word to dynamically decide the behavior at runtime.
Duck class
Note: Here we are using Composition instead of inheritance.
Favor composition over inheritance
This allows lot more flexibility to the code.
MallardDuck class
RedHeadDuck class
RubberDuck class
DecoyDuck class
FlyBehavior interface
FlyWithWings class
FlyNoWay class
QuackBehavior interface
Quack class
Squeak class
MuteQuack class
App class
Step 3 Output
These things points to a Design pattern "Strategy Pattern".
The Strategy Pattern defines a family of algorithms, encapsulate each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.