Unwrapping the Decorator Pattern with Java
Abstract
The following document purposes an object oriented design solution that can be applied to many common business scenarios. In this brief paper I describe how to implement the decorator design pattern using the Java Programming language. I will go over the main problems of using too many subclasses, provide the user with Unified Modeling Language (UML) diagrams to visually represent an application, provide the reader with a small application illustrating the decorator pattern and finally provide the reader with the pros and cons of using the decorator pattern,. This document infers that the reader has a basic understanding of UML and how to use an object oriented programming language. While this paper uses Java for reader simplicity, the user can apply the Decorator pattern methodology to most object oriented scripting and programming languages such as C# and PHP. In addition I will provide definitions of the common object oriented programming terms presented in this document. PurposeIn this brief tutorial I will attempt to solve a very common application development dilemma using a generic real world scenario; With this knowledge the developer will add a tidbit of knowledge to their "Mental Tool Kit" . In addition I will provide a few resources in which the programmer will be able to seek out other design pattern knowledge.
Defined
In (Gamma, Helm, Johnson, & Vlissides, 1997) the decorator is defined as "Attach[ing] additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality". So what does this mean in basic programming terms? Fundamentally it means that we are going to "wrap" or "decorate" objects with other objects to produce the behavior we are looking for. It also provides us with a solution to a common subclassing nightmare that many programmers decide to use, inadvertently.
Figure 1 Object Wrapping in this situation the objects call the methods of the wrapping objects to add to our final output.
Scenario
You have a client that specializes in selling burgers. The client is relatively new in the market and his business is growing at an exponential rate. The client needs a program that is flexible enough to handle various sandwich combinations and adapt to there every changing needs. The current software that the client uses does not account for the new sandwich combinations they plan to introduce.
The first programmer assigned to this task used basic programming techniques to give the client exactly what they needed- at the time. After looking at the source code you find that it is full of subclasses, all of which are extending the main class's methods and properties. You also find it very hard to make any changes to the program because there are just too many dependent relationships in the code, i.e. if you change something here..., it will break something else in the program. What do you do? Do you spend hours trying to figure out the huge programming "spaghetti" code or do you re-write the code and make it more developer friendly? In each case you may find yourself spending just as much time to produce the results you need. But if you decide to utilize the decorator pattern and refactor the code, the next time the client needs changes your time will be more wisely spent.

Figure 2a Subclass overload; each time we create another subclass we have to continually change the description of the sandwich name and price.

Figure 2b The Decorator Pattern
In figures 2a and 2b we can see both of our options in UML diagrams. In figure 2a we have a subclassing overload nightmare which can quickly get out of control. In figure 2b we have a tidier program, utilizing the Decorator Design pattern; which becomes easier to manage when we add more sandwich types, price changes and condiments.
Since we have many other clients and we enjoy becoming more productive and efficient at what we do. We have decided to use the Decorator pattern approach.We can start our programming task by first creating a main abstract class defined below:
public abstract class Sandwich{
String sandwichName = " Sandwich";
public abstract getSandwichName(){
return sandwichName;
}
public abstract double price();
}
Next we extend the Sandwich class by creating an abstract decorator class below:
public abstract String getSandwichName();
}
Now lets create some concrete classes from the abstract SandwhichCondiment decorator:
// lets add a slice of cheese
public class Cheese extends SandwhichCondiment{
// this will take on the data type of the Sandwich main class
Sandwich sandwich;
public Cheese (Sandwich sandwich){
this.sandwich = sandwich;
}
public String getSandwichName(){
return sandwich.getSandwichName() + "+ Cheese";
}
public double price(){
return .15 + sandwich.price();
}
}
Our next concrete class to add some lettuce:
public class Lettuce extends SandwhichCondiment{
// this will take on the data type of the Sandwich main class
Sandwich sandwich;
public Lettuce (Sandwich sandwich){
this.sandwich = sandwich;
}
// this will add the name of the sandwich plus
// any elements we decide to use
public String getSandwichName(){
return sandwich.getSandwichName() + "+ Lettuce";
}
// lets add to the price dynamically
public double price(){
return .05 + sandwich.price();
}
}
Our next concrete class to add some Tomato:
public class Tomato extends SandwhichCondiment{
// this will take on the data type of the Sandwich main class
Sandwich sandwich;
public Tomato (Sandwich sandwich){
this.sandwich = sandwich;
}
public String getSandwichName(){
return sandwich.getSandwichName() + "+ Tomato";
}
// lets add to the price dynamically
public double price(){
return .05 + sandwich.price();
}
}
Our next concrete class to add some Pickle:
public class Pickle extends SandwhichCondiment{
// this will take on the data type of the Sandwich main class
Sandwich sandwich;
public Pickle (Sandwich sandwich){
this.sandwich = sandwich;
}
public String getSandwichName(){
return sandwich.getSandwichName() + "+ Pickle";
}
// lets add to the price dynamically
public double price(){
return .05 + sandwich.price();
}
}
As you can see, there is a basic pattern beginning to develop with the concrete classes, you can add as many as you need to satisfy your client’s needs without affecting the rest of the application.
Now we can add a couple of concrete classes to extend the Sandwich class’s properties and methods:
The Burger Class:
public class Burger extends Sandwich{
// constructor
public Burger(){
sandwichName ="Classic Burger";
}
public double price(){
return 3.29;
}
The Turkey Burger Class:
// constructor
public Burger(){
sandwichName ="Turkey Burger";
}
public double price(){
return 5.99;
}
The Turkey and Burger classes are just the beginning, by using the Decorator Patterns approach we can successfully create as many different base sandwich types that we need without going through all the lines of code looking for cause and effect relationships e.g. if we decided to add a grilled chicken sandwich class we would merely have to give it a sandwichName value and price to utilize the toppings presented in our Decorator’s concrete classes.
Testing our ApplicationTo test the efficiency of the program we use a simple main class to display our results.
public class testOurBugers {
public void static main (String args[]){
// instantiate a new burger object
Sandwich ourCreatedSandwich = new Burger();
//lets create a Classic burger with cheese, lettuce, tomato and pickle
ourCreatedSandwich = new Cheese(ourCreatedSandwich);
ourCreatedSandwich = new Lettuce(ourCreatedSandwich);
ourCreatedSandwich = new Tomato(ourCreatedSandwich);
ourCreatedSandwich = new Pickle(ourCreatedSandwich);
System.out.println(ourCreatedSandwich.getSandwichName() + "= $" + ourCreatedSandwich.price();
//lets create a Turkey burger with lettuce and tomato.
Sandwich ourCreatedTurkeyBurger = new Turkey();
ourCreatedTurkeyBurger = new Lettuce(ourCreatedTurkeyBurger);
ourCreatedTurkeyBurger = new Tomato(ourCreatedTurkeyBurger);
System.out.println(ourCreatedTurkeyBurger.getSandwichName() + "= $" + ourCreatedTurkeyBurger.price();
}
}
The output is just 2 different sandwich combinations out of several possible scenarios.
How it Works
By instantiating a Turkey and a Burger object we are extending the attributes and methods from the Sandwich class. To make use of the SandwhichCondiment Class and decorate our objects we wrap them with any of the condiment concrete classes that we need on our burgers. With each new object instantiation we are essentially decorating the objects with another object see figure 1. This will allow us the opportunity to manipulate our objects at runtime, dynamically, by having each of the objects calling methods on each of wrapped objects we create.Pros and Cons
We have seen some of the pros and benefits of using the decorator pattern such as maintaining applications with greater ease, manipulating objects dynamically at run time and allowing our applications to have greater flexibility. As with any solution there are also cons that can creep into your application, if you are not careful. One of which is the decorator’s transparency i.e. if the programs UML is not made available to the new developers it can easily go unnoticed. This can create a significant problem because any changes that are made to the application can create mass confusion and undesired results. Another issue is that junior developers may not be able to understand what you have implemented and one can easily get perplexed if the creation of multiple small classes is present.
Conclusion
When creating programs that require a mass amount of subclasses to get the desired functionality needed, implementing the decorator pattern methodology can possibly improve your a program’s scalability and maintenance. In the “Scenario” section we created a small generic application that can be easily updated to create more types of sandwiches with different prices and topping combinations. In this application the Decorator pattern achieved the desired results in lieu of the said pros and cons.
DefinitionsAbstract
[A] formally unfinished class or method, marked with the keyword abstract. It is a way of preventing someone from instantiating a class that is supposed to be extended first. An abstract class is deliberately missing some or all of the method bodies. An abstract method is deliberately missing its method body. An abstract class is similar to an interface which is missing all the method bodies. An abstract class provides a base for someone to extend an actual class. You can’t use new on abstract classes, but you can use abstract references, which always point to objects of a class that extends the abstract class. Interfaces are implicitly abstract as are all their methods (Green, 2008).
Class
A class in Java is much like one in C++. It consists of a group of related methods and variables lumped together under one name. The static class variables are for class-as-a-whole data. They are allocated only once at load time and are shared by all instances of objects of that class. The instance variables, are allocated inside each object of that class. Static class methods work when there is no current object. They can only reference static class variables and static methods, unless of course they allocate an object and then use explicit references to the instance variables. Instance methods work by default on the fields of the current this object (Green, 2008).
Inheritance
When a class extends a superclass with additional methods and instance variables we say the new class inherits the methods and variables of the superclass. The new class may override some of the superclass’s methods and shadow some of its variables. Not all the inheritance is visible (i.e. available for you to use directly in your subclass), but it is present. Be careful, the inheritance rules for [public/protected/package/private] [static/instance] [method/variable] [abstract/actual] [class/interface] are all different (Green, 2008).
Object-Oriented
Object-oriented to Java programmers refers to the way you organize methods in classes that work on the current object. Java supports inheritance and polymorphism via shadowing, overriding and overloading. The big advantage of object-oriented programming is the way you can easily create variants of the usual behaviors without cloning code. This makes maintaining the code much easier since when you later want to change something, you need to change it in only one place, not in all the myriad clones (Green, 2008).
Subclass
This is the reverse of the way a mathematician might look at it. From the point of view of mathematical set theory, Dalmatian has a superset of the methods of Dog (Green, 2008).
UML
UML stands for Universal Modeling Language. It is a modeling technique designed by Grady Booch, Ivar Jacobson, and James Rumbauch of Rational Rose. It is used for OOAD (Object Oriented Analysis and Design) It is supported by a broad base of industry-leading companies which, arguably, merges the best of the various notations into one single notation style. It is rapidly being supported by many tool vendors, but the primary drive comes from Rational Rose (Green, 2008).
Additional Resources
Cooper, J. W. (1998). The Design Patterns Java Companion. Retrieved April 4, 2008, from patterndepot.com: http://www.patterndepot.com/put/8/JavaPatterns.htm
Design Patterns. (n.d.). Retrieved April 4, 2008, from SourceMaking.com: http://sourcemaking.com/design_patterns/decorator
GUO International.(2008).Java Design Patterns At a Glance. Retrieved April 4, 2008, from Javacamp.com:
http://www.javacamp.org/designPattern/
McLaughlin, Brett, Pollice, Gary & West, David.(2007).Head First Object-Oriented Analysis and Design: A Brain Friendly Guide to OOA&D. Sebastopol: O'rielly Media, Inc.
References:
Cooper, J. W. (1998). The Design Patterns Java Companion. Wilton, Connecticut: Addison-Wesley.
Cunningham & Cunningham, Inc. (2000). History Of Patterns. Retrieved March 21, 2008, from Cunningham & Cunningham, Inc.: http://www.c2.com/cgi-bin/wiki?HistoryOfPatterns
Deitel, H. M., & Deitel, P. J. (2004). Java How to Program (4th Edition). New York City: Prentice Hall.
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. M. (1997). Design Patterns Elements of Reusable Object-Oriented Software. Upper Saddle River: Pearson Education Corporation.
Green, R. (2008). Canadian Mind Products Java & Internet Glossary. Retrieved April 30, 2008, from Canadian Mind Products: http://mindprod.com/jgloss/jgloss.html
Rumbaugh, J., Jacobson, I., & Booch, G. (1999). The Uniified Modeling Language Reference Manual. Massachusetts: Addison-Wesley.
Snarski, R. (2007). Technical Communications in the Information Age. Acton: Copley Custom Textbooks.


