Welcome to my Decorator Design Pattern Tutorial. The Decorator allows you to modify an object dynamically. You would use it when you want the capabilities of inheritance with subclasses, but you need to add functionality at run time.
It is more flexible than inheritance. The Decorator Design Pattern simplifies code because you add functionality using many simple classes. Also, rather than rewrite old code you can extend it with new code and that is always good.
If you like videos like this, it helps if you tell Google [googleplusone]
Sharing is nice
Code from the Video
PIZZA.JAVA
// Blueprint for classes that will have decorators public interface Pizza { public String getDescription(); public double getCost(); } /* public abstract class Pizza{ public abstract void setDescription(String newDescription); public abstract String getDescription(); public abstract void setCost(double newCost); public abstract double getCost(); // I could use getter and setter methods for every // potential Pizza topping } */
THREECHEESEPIZZA.JAVA
// By going this route I'll have to create a new subclass // for an infinite number of pizza. // I'd also have to change prices in many classes // when just 1 Pizza topping cost changes // Inheritance is static while composition is dynamic // Through composition I'll be able to add new functionality // by writing new code rather than by changing current code public class ThreeCheesePizza extends Pizza{ private String description = "Mozzarella, Fontina, Parmesan Cheese Pizza"; private double cost = 10.50; public void setDescription(String newDescription) { description = newDescription; } public String getDescription() { return description; } public void setCost(double newCost) { cost = newCost; } public double getCost() { return cost; } }
PLAINPIZZA.JAVA
// Implements the Pizza interface with only the required // methods from the interface // Every Pizza made will start as a PlainPizza public class PlainPizza implements Pizza { public String getDescription() { return "Thin dough"; } public double getCost() { System.out.println("Cost of Dough: " + 4.00); return 4.00; } }
TOPPINGDECORATOR.JAVA
// Has a "Has a" relationship with Pizza. This is an // Aggregation Relationship abstract class ToppingDecorator implements Pizza { protected Pizza tempPizza; // Assigns the type instance to this attribute // of a Pizza // All decorators can dynamically customize the Pizza // instance PlainPizza because of this public ToppingDecorator(Pizza newPizza){ tempPizza = newPizza; } public String getDescription() { return tempPizza.getDescription(); } public double getCost() { return tempPizza.getCost(); } }
MOZZARELLA.JAVA
public class Mozzarella extends ToppingDecorator { public Mozzarella(Pizza newPizza) { super(newPizza); System.out.println("Adding Dough"); System.out.println("Adding Moz"); } // Returns the result of calling getDescription() for // PlainPizza and adds " mozzarella" to it public String getDescription(){ return tempPizza.getDescription() + ", mozzarella"; } public double getCost(){ System.out.println("Cost of Moz: " + .50); return tempPizza.getCost() + .50; } }
TOMATOSAUCE.JAVA
public class TomatoSauce extends ToppingDecorator { public TomatoSauce(Pizza newPizza) { super(newPizza); System.out.println("Adding Sauce"); } // Returns the result of calling getDescription() for // PlainPizza, Mozzarella and then TomatoSauce public String getDescription(){ return tempPizza.getDescription() + ", tomato sauce"; } public double getCost(){ System.out.println("Cost of Sauce: " + .35); return tempPizza.getCost() + .35; } }
PIZZAMAKER.JAVA
public class PizzaMaker { public static void main(String[] args){ // The PlainPizza object is sent to the Mozzarella constructor // and then to the TomatoSauce constructor Pizza basicPizza = new TomatoSauce(new Mozzarella(new PlainPizza())); System.out.println("Ingredients: " + basicPizza.getDescription()); System.out.println("Price: " + basicPizza.getCost()); } }
Now I got the point, the ‘loop’ of the toppings stop because you will always have a PlainPizza that don’t extend ToppingDecorator. So it is like a list of elements(Decorators).
Yes you have it! That is what makes this pattern great. I made another video on the Decorator pattern just to show how nice it is if you’d like a second look.
Hey brother,
in THREECHEESEPIZZA.JAVA, probably you have mistakenly extends from Pizza interface. should it be implement…
🙂
Thanks for the video. I think it helped me get the idea.
However, I’m wondering if the constructor for Mozzarella should say only:
public Mozzarella(Pizza newPizza) {
super(newPizza);
System.out.println(“Adding Moz”);
}
Likewise, a constructor for PlainPizza should be added like so:
public PlainPizza() {
System.out.println(“Adding Dough”);
}
I think this works, because currently if you had a pizza with only tomato sauce it will say you have thin dough but it would never get added. The price for the dough does get added to the cost. Do you concur? If not, can you explain what I’m missing?
Thanks,
Ken
Yes it could have been done that way and your way does make more sense since it really doesn’t make sense to have mozzarella do anything with the dough. I did it that way to limit the number of classes
Hi.. Good one. Have a question though. Why “Adding Dough” is mentioned in Moz.java… Does that mean we are printing adding dough only when we are adding Moz right? So, if I just want Sauce and Dough, the output will not print Adding Dough but the cost could be 4.35$.
PS: I didn’t tried out the program yet. Just got the doubt as you explain.
Never mind. Just saw one more comment like mine 🙂
I’m glad you got your question answered. Sorry I couldn’t get to you quicker
Have you forgotten to answer my question? Please help.
I’m sorry I got a bit behind on comments lately. I’ll go through them and see if I can find it
It will be great if you could mention the limitations of design patterns along with their benefits..
The limitations are normally the same for each one. All to often people force them into code when they just make the code more complicated. That is the major skill that one must develop. It is just as important to not use them as it is to use them.
Hi Derek,
First of all, thanks a ton for making these tutorials, you have really helped me to get a better understanding of design patterns and when to use them.
I have a small doubt though, Why is ToppingDecorator class implementing the interface Pizza, doesn’t it break the “Is A” principle for inheritance, after all ToppingDecorator itself is not a pizza. Can’t we just use aggregation to achieve the desired result.
Thanks in advance !!
I maybe should have used a different name then Pizza in this situation. I see how it can cause confusion
hey i ve been a good fan of your videos, I’ve been using a tool called sublime text lately but it seriously lacks somewhere in code completion. if not sublime what would be the best for c++ development, i mean something very fast and efficient and low power consuming.
Thank you 🙂 On OSX I use Code::Blocks. Some people really like XCode as well. On Windows Visual Studio is the best by far. Eclipse CDT is okay for both OSs. Code::Blocks works on Linux as well. I hope that helps.