Background
This pattern employes a very important OO design principle -- Classes should be open for extension but closed for modification.
- Creational
- Structural
- Behavioral
Lets take an example to understand this better. Lets say you have opened a Pizza shop and you offer various types of Pizzas.
You then created classes for each type of Pizza. Now that you are very well versed with following design principle -
You then created classes for each type of Pizza. Now that you are very well versed with following design principle -
- Code for interface and not implementation
Generic Class Diagram
To the Code....
Lets first create an interface - Pizza.
public interface Pizza { int getCost(); }
Now lets create concrete classes for Pizza -
public class PaneerPizza implements Pizza { @Override public int getCost() { return 3; } }
and
public class ChickenPizza implements Pizza { @Override public int getCost() { return 5; } }
And now lets create decorator class. Remember decorator class will implement Component and will also have an instance of Component in it. Also the operation method which is this case is getCost() will be abstract.
public abstract class PizzaDecorator implements Pizza { Pizza pizza; public abstract int getCost(); }
and now lets create concrete classes for Toppings which will extend PizzaDecorato.
public class MushroomToppings extends PizzaDecorator { public MushroomToppings(Pizza pizza) { this.pizza = pizza; } @Override public int getCost() { return 2 + pizza.getCost(); } }
and
public class CornTopping extends PizzaDecorator { public CornTopping(Pizza pizza) { this.pizza = pizza; } @Override public int getCost() { return 1 + pizza.getCost(); } }
and that's all with the model classes. Now lets simulate it and see,
/** * @author athakur */ public class PizzaSimulation { public static void main(String args[]) { Pizza pizza = new ChickenPizza(); System.out.println("Pizza cost : " + pizza.getCost()); Pizza pizzaWithCornToppings = new CornTopping(pizza); System.out.println("Pizza cost : " + pizzaWithCornToppings.getCost()); Pizza pizzaWithCornAndMushroomToppings = new MushroomToppings(pizzaWithCornToppings); System.out.println("Pizza cost : " + pizzaWithCornAndMushroomToppings.getCost()); } }
And the output is -
Pizza cost : 5
Pizza cost : 6
Pizza cost : 8
Now go back to each Pizza and Topping class and verify the output. It's pretty straight forward. See how we could dynamically add toppings and compute total cost without actually modifying the original class? That the power of Adapter patter.
NOTE : In decorator pattern decorator implements the component and also composes the component.
NOTE : In adapter pattern adapter implements the target and composes the adaptee.
Related Links
Summary
- Decorator pattern does not alter any interface. It simply adds responsibility.
- Adapter pattern Converts one interface (Adaptee) to another (Target) for compatibility.
- Facade pattern simplifies interface for complex subsystem subclasses.
No comments:
Post a Comment