Decorator Pattern: Introduction

The common objective of the classic Gang of Four structural patterns that we’ve learned – Adapter, Bridge, and Composite is to identify how to realize complex relationships between classes and objects in a simple and flexible way. The decorator pattern also has the same objective but addresses a different problem area.

While thinking about extending functionality, the first thing which is likely to occur to a new programmer is inheritance. However, inheritance may not be the ideal solution in all situations. When you inherit functionality through subclassing, the functionality is statically set at compile time and it doesn’t always lead to the most flexible nor maintainable designs. If you need to add new features, code modifications are required, which is a violation of the Open Closed Principle.

Instead, you can attach new responsibility to an object dynamically. This is exactly the intended use of the decorator pattern. Per the Gang of Four – “Attach additional responsibilities to an object dynamically”. But how do you do this? By using Composition. With composition, you can dynamically add multiple new responsibilities to objects at run time. The great thing here is that the object doesn’t need to be aware of it, and your design conforms to the Open Closed Principle. We often look to the elegance of a great object oriented programming language such as Java, while overlooking the simplicity of using composition to solve a problem.

Let’s look at a problem scenario and see how the decorator pattern can solve it.

Participants of the Decorator Pattern

Consider a florist who sells flower bouquets, such as rose bouquet, orchid bouquet, and so on. When a customer walks in, the florist describes the bouquets and tells their prices. We can model the requirements with a FlowerBouquet abstract base class and subclasses for specific bouquets.

Customers, in addition to a bouquet, can ask the florist to decorate it with paper wrappings, ribbon bows, and glitters for which the florist charges extra. To address the new requirement, we can add new subclasses of FlowerBouquet, one each to represent a bouquet with an additional decoration, and this is how our design looks like now.

What we have is “class explosion” and that too while adding only a single decoration to a bouquet. Imagine representing a bouquet with multiple decorations, for example a rose bouquet with both ribbon bow and glitter, or an orchid bouquet with paper wrap, ribbon bow, and glitter. Some more considerations:

What if we want a rose bouquet with double paper wrap?

What if we want to add a new lily bouquet?

What if we want to add new ornamental leaves decoration?

Clearly our design is flawed, but this is an ideal use case for the decorator pattern. By using the decorator pattern, we can create a flower bouquet and dynamically decorate it with any numbers of features at run time. Without the flower bouquet knowing it that is “being decorated”. For that, we will create an abstract base class FlowerBouquet and specific subclasses RoseBouquet and OrchidBouquet to extend from it. We will also create an abstract FlowerBouquetDecorator class to extend FlowerBouquet. For each decorator, we will create the Glitter, PaperWrapper, and RibbonBow classes to extend from FlowerBouquetDecorator. This is how the design will be.

In the diagram above, the most important thing to observe is the relationship between FlowerBouquet and FlowerBouquetDecorator. We have two types of relationships:

Inheritance by sub classing FlowerBouquetDecorator from FlowerBouquet in order to have the correct type.

Composition by composing FlowerBouquetDecorator with FlowerBouquet in order to add new behavior.

Let’s now look how our classes map to the participants of the decorator pattern:

Component (FlowerBouquet): Is an abstract base class that can be decorated with responsibilities dynamically.

ConcreteComponent(RoseBouquet and OrchidBouquet): Are concrete classes that extends Component to represent objects to which additional responsibilities can be attached.

Decorator (FlowerBouquetDecorator): Is an abstract class that extends Component and acts as the base class for concrete decorator classes.

ConcreteDecorator (PapperWrapper, RibbonBow, and Glitter): Are concrete classes that extends Decorator to decorate Components with responsibilities.

Applying the Decorator Pattern

To apply the decorator pattern to the flower bouquet example, let’s write the abstract base class- the Component.

FlowerBouquet.java

Java

1

2

3

4

5

6

7

8

9

packageguru.springframework.gof.decorator.components;

publicabstractclassFlowerBouquet{

Stringdescription;

publicStringgetDescription(){

returndescription;

}

publicabstractdoublecost();

}

In the FlowerBouquet class above, we wrote a description instance variable, a getDescription() method that returns it, and an abstract cost() method. We will next write the ConcreteComponent classes.

RoseBouquet.java

Java

1

2

3

4

5

6

7

8

9

10

11

packageguru.springframework.gof.decorator.components;

publicclassRoseBouquetextendsFlowerBouquet{

publicRoseBouquet(){

description="Rose bouquet";

}

publicdoublecost(){

return12.0;

}

}

OrchidBouquet.java

Java

1

2

3

4

5

6

7

8

9

10

11

packageguru.springframework.gof.decorator.components;

publicclassOrchidBouquetextendsFlowerBouquet{

publicOrchidBouquet(){

description="Orchid bouquet";

}

publicdoublecost(){

return29.0;

}

}

We extended both the classes above from FlowerBouquet and initialized the description variable in their constructors. We also implemented the cost() method in each class to return their cost. Now that we have written the components, we will write the Decorator.

FlowerBouquetDecorator.java

Java

1

2

3

4

5

6

7

8

packageguru.springframework.gof.decorator.decorators;

importguru.springframework.gof.decorator.components.FlowerBouquet;

publicabstractclassFlowerBouquetDecoratorextendsFlowerBouquet{

publicabstractStringgetDescription();

}

We extended the FlowerDecorator class from FlowerBouquet and declared an abstract getDescription() method. We did it because we want all our flower decorator classes to implement getDescription() to include both the description of the decorator and the flower bouquet it is decorating. This will get clearer once we write the ConcreteDecorator classes. Lets, start with Glitter.

Glitter.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

packageguru.springframework.gof.decorator.decorators;

importguru.springframework.gof.decorator.components.FlowerBouquet;

publicclassGlitterextendsFlowerBouquetDecorator{

FlowerBouquet flowerBouquet;

publicGlitter(FlowerBouquet flowerBouquet){

this.flowerBouquet=flowerBouquet;

}

publicStringgetDescription(){

returnflowerBouquet.getDescription()+", glitter";

}

publicdoublecost()

{

return4+flowerBouquet.cost();

}

}

We extended the Glitter class from FlowerDecorator, and added a FlowerBouquet instance variable (Composition) to hold the flower bouquet we are wrapping. The instance variable gets initialized at run time through the constructor call. We then implemented the getDescription() method and returned both the description of this decorator and the flower bouquet it is decorating. We also implemented the cost() method to add the cost of this decorator to the cost of the flower bouquet it is decorating. We will similarly write the other decorator classes.

PaperWrapper.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

packageguru.springframework.gof.decorator.decorators;

importguru.springframework.gof.decorator.components.FlowerBouquet;

publicclassPaperWrapperextendsFlowerBouquetDecorator{

FlowerBouquet flowerBouquet;

publicPaperWrapper(FlowerBouquet flowerBouquet){

this.flowerBouquet=flowerBouquet;

}

publicStringgetDescription(){

returnflowerBouquet.getDescription()+", paper wrap";

}

publicdoublecost()

{

return3+flowerBouquet.cost();

}

}

RibbonBow.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

packageguru.springframework.gof.decorator.decorators;

importguru.springframework.gof.decorator.components.FlowerBouquet;

publicclassRibbonBowextendsFlowerBouquetDecorator{

FlowerBouquet flowerBouquet;

publicRibbonBow(FlowerBouquet flowerBouquet){

this.flowerBouquet=flowerBouquet;

}

publicStringgetDescription(){

returnflowerBouquet.getDescription()+", ribbon bow";

}

publicdoublecost()

{

return6.5+flowerBouquet.cost();

}

}

Let’s now write some test code to see how the decorator pattern works at runtime.

FlowerBouquetTest.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

packageguru.springframework.gof.decorator.components;

importguru.springframework.gof.decorator.decorators.Glitter;

importguru.springframework.gof.decorator.decorators.PaperWrapper;

importguru.springframework.gof.decorator.decorators.RibbonBow;

importorg.junit.Test;

publicclassFlowerBouquetTest{

@Test

publicvoidtestFlowerBouquet(){

/*Rose bouquet with no decoration*/

FlowerBouquet roseBouquet=newRoseBouquet();

System.out.println(roseBouquet.getDescription()

+" $ "+roseBouquet.cost());

/*Rose bouquet with paper wrapper, ribbon bow, and glitter*/

FlowerBouquet decoratedRoseBouquet=newRoseBouquet();

decoratedRoseBouquet=newPaperWrapper(decoratedRoseBouquet);

decoratedRoseBouquet=newRibbonBow(decoratedRoseBouquet);

decoratedRoseBouquet=newGlitter(decoratedRoseBouquet);

System.out.println(decoratedRoseBouquet.getDescription()

+" $ "+decoratedRoseBouquet.cost());

/*Orchid bouquet with double paper wrapper and ribbon bow*/

FlowerBouquet decoratedOrchidBouquet=newOrchidBouquet();

decoratedOrchidBouquet=newPaperWrapper(decoratedOrchidBouquet);

decoratedOrchidBouquet=newPaperWrapper(decoratedOrchidBouquet);

decoratedOrchidBouquet=newRibbonBow(decoratedOrchidBouquet);

System.out.println(decoratedOrchidBouquet.getDescription()

+" $ "+decoratedOrchidBouquet.cost());

}

}

In Line 13 – Line 15 of the test class above, we first instantiated a RoseBouquet and printed its description and cost. In Line 18 – Line 23, we again instantiated a RoseBouquet, and this time we wrapped it with the PaperWrapper, RibbonBow, and Glitter decorators before printing its description and cost. In Line 26 – Line 31, we instantiated a OrchidBouquet, and wrapped it twice with PaperWrapper and then once with RibbonBow before printing its description and cost.

Conclusion

The decorator pattern is a great solution to dynamically extend behavior without subclassing, but it often results in a large number of decorator classes. While there are no complexities in creating the classes and applying the pattern, it can sometimes become overwhelming for new programmers to figure out and use existing decorator-based code. The java.io API is largely based on the decorator pattern, and now that you have learned it, you will be at ease while wrapping input and output streams with decorator classes, such as BufferedInputStream and DataInputStream. Also, if you feel that clients might find your decorator-based code complex, you can always encapsulate the complexity by using the Factory Method, Abstract Factory, or Builder creational patterns.

Decorator pattern also comes in use during Enterprise Application Development with the Spring Framework. You will often need to perform tasks, such as transaction, cache synchronization, and security related tasks. If you don’t want to risk cluttering up the business code, use decorators. Often, use of the decorator pattern will lead you to cleaner and more maintainable code.

5 comments on “Decorator Pattern”

sun

January 14, 2016 at 9:29 am

How would this be implemented using the spring framework? Could the decorations be added dynamically in some way?