Decorator Pattern

Task - Design beverage shop with multiple toppings on it.
Initially the shop was not offering the toppings only a specific beverage.So design would look like this.

So you they have expanded and started offering the toppings as well, in similar way we have to do all commbination of beverage and toppings.

Try to answer below question -
What happens when the price of milk goes up? - we have to edit so many classes cost function.
What do they do when they add a new topping? - we have to create so many new classes for new topping with different combination.
What design prinicples we are violating? - we are violating 2 DP
Design patterns we have learned so far -
Encapsulate what varies.
Favor composition over inheritance.
Program to interfaces, not implementations.
Strive for loosely coupled designs between objects that interact - observer.
Classes should be open for extension but closed for modification - decorator.
Thought - Why do we need all these classes? can't we just use instance variables and inheritance in the superclass to keep track of the condiments?

This solves the problem of class explosion.
Try to ans below questions -
What if price changes for condiments? we have to make changes in main code. which shouldn't be open for modification.
What if we want to add new condiments? same for this.
What if beverage is ice tea which does not need to inherit hasWhip() - this design forces to inherit.
What if customer wants a double mocha? - we can't achieve this with this design.
Note -
When I inherit behaviour by subclassing, that behavior is set statically at compile time. In addition, all subclasses must inherit the same behavior.
If however, I can extend an object's through compostion, then I can do this dynamically at runtime.
Design Principle [Main Concept]
Classes should be open for extension but closed for modification.
Note - Open close principle may create complex code, it should be used whenever required.
Here comes the decorator pattern
It attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

wrt to beverage

We're subclassing the abstract class beverage in order to have the correct type not to inherit its behavior. The behavior comes in through the composition of decorators with the base components as well as other decorators
WorkFlow for revision -
Create a beverage from concreteComponent and pass the beverage inside condiment's object recursively and condiment as decorator.
Beverage beverage = new decorator(new decorator(new concreateComponent()));



