What is Decorator Design Pattern?

Decorator design pattern falls under the structural design pattern category. As the name implies, decorator pattern provides some kind of decorational effect on the original object. That is, the pattern provides the ability to add new features and behaviors to a base object without altering its existing structure. That is there will be additional features added to the original object. The component, which adds these additional features is called as the ‘Decorator’. The ‘Decorator’ class in this pattern act as a wrapper object which dynamically attaches additional features to the original object at run-time.

The GoF definition of decorator pattern,

‘Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality’

As in the definition, the main intent of decorator pattern is to attach additional responsibilities and features dynamically to an object. However, at the same time, other instances or base class will not be affected by the new dynamic change. Only the individual object will receive the new modification. Since this pattern solves the dynamic feature addition at run-time, it resolves the problem of the complex sub-classing requirement when extending base class functionality.

Real Life Example for Decorator Design Pattern

It’s like adding cheese topping to a pizza or adding walnut and chocolate source topping to an ice-cream. You can add any kind of cheese or sauce to the pizza just before serving to the customer, yet base pizza remains unchanged. Likewise, you can request walnut or cherries on a vanilla ice cream or you can change the mind and ask to add only chocolate topping and cherry sauce. Base vanilla ice cream won’t change and you can have whatever topping you like on the ice cream. If there are 20 people in the group, they can request 20 vanilla ice creams with different toppings, nuts, and fruits on time of serving.

Problem solved by the Decorator Pattern

The problem occurs when an application wants to incorporate additional features and behaviours to objects at run-time. Moreover, it’s not only one feature, there can be multiple features and functionalities. Therefore, acquiring that situation will definitely become a lengthy and complex coding hack to a developer. You may thing inheritance and sub-classing will help to resolve the situation. However, those won’t support due to certain limitations on those approaches.

Inheritance and sub-classing effects at compile-time that is statically, you have to pre-configure the required additional features and functionalities if planning to use those approaches. In addition, the new options will attach to all the objects from those sub-classes, which is not a definite requirement at this situation. Hence, we need a way to fill both of those gaps. Decorator comes into the play to solve this problem.

What is Decorator Class?

Decorator class is the component, which inserts new options to the base object dynamically. Additionally, it will not do any modification to other objects from the same class since it inserting the new options at run-time. The ‘Decorator’ is an interface or an abstract class in java programming. It provides a platform to implement additional features and functionalities. Then several classes will take the ‘Decorator’ as the base and implement the concrete additional behaviors, which are requested by the original object at run-time. Hence, ‘Decorator’ acts as a wrapper object to the original object.

How Does Decorator Pattern work?

‘Decorator’ is an abstract component, which holds the generic features. Each new feature and function is implemented inside concrete decorator classes. That is ‘Decorator’ act as an interface which again extended by the concrete decorator classes.  The base object act as an input to extended decorator concrete classes. Both the ‘Decorator’ and the base class use the same interface to derive themselves. Since the ‘Decorator’ is a wrapper object to the base object, each concrete decorator class includes an instance of a base object. The base object remains intact and hidden inside the decorator object. However, the final object will be a fully decorated complete product, which contains the required additional effects. That is the beauty of decorator pattern.

Structure of the Decorator Pattern

In this pattern, you can find two kinds of interface – concrete component relationships. One interface uses to provide the abstraction for the base object and for the decorator object. Both objects use the same base component interface since decorator is the wrapper for the base object. The second interface is used to abstract the decorator hierarchy. Each concrete component implements the decorator interface in order to incorporate the original features and behaviours.

The Class Diagram of the Decorator Pattern

 

Decorator design pattern Design Pattern

Let explore the details of each component in the above diagram (Figure 1),

Component Interface

This is the base interface or abstract class used by both the ‘Decorator’ and the original concrete component. If this act as an abstract class, it includes the standard members and behaviours that have to be implemented by those two main classes. If there are, no any common behaviours let it exist as an interface.

Concrete Component

This is the original object, which needs to be altered by the decorators at the run-time. This class inherits from the component interface. There can be multiple concrete components that expecting to get the decorator effect in the future.

Decorator Interface

This is the base interface or abstract class for all the subsequent concrete decorators. Decorator will conforms to the ‘Component’ interface by implementing it or extending it based on the nature of ‘Decorator’. The decorator must keep a reference to the original object in order to send it as an input to the concrete decorators to add the additional features dynamically. Hence, the ‘Decorator’ maintains a ‘HAS-A’ relationship with the ‘Component’.

Concrete Decorator

This concrete class extends the abstract decorator. It takes the base component and adds the additional options dynamically. There can be more than one concrete decorator to an application.

Example for Decorator Design Pattern

Let’s take a juice bar which makes different kinds of juices. Their most popular product is the milkshake. There are many flavours of milkshakes to select. Imagine three friends went there and ordered a banana milkshake, peanut butter shake and chocolate milkshake.

We need to represent this scenario for the decorator pattern implementation. If we study the scenario further, we can identify that the base component is a milk with sugar and salt. Then there are three kinds of additional features attached to this milkshake on the serving time or blending moment dynamically. Thus, we can break our class structure as below,

  1. MilkShake interface: This is the base component interface for both the original object and decorator object
  2. ConcreteMilkShake : This is the actual base milkshake which use to make the customer required flavour of milkshake
  3. MilkShakeDecorator: This is the abstract decorator for the subsequent concrete decorator classes.
  4. BananaMilkShake: This is one of the concrete implementation of the decorator interface. This decorator class adds the banana flavour decoration to the concrete milkshake. Banana is the additional state or feature in this particular instance.
  5. PeanutButterShake : Special decoration for this milkshake instance is peanut butter
  6. ChocolateMilkShake : Special decoration for this milkshake instance is Chocolate
  7. MilkShakeClient : The class which requests the specific instance from the juice bar

Class  Diagram for the Example

 

Decorator design pattern example
Decorator pattern example

You can see the relevant code samples for above scenario,

MilkShake.java

ConcreteMilkShake.java

MilkShakeDecorator.java

BananaMilkShake.java

PeanutButterMilkShake.java

ChocolateMilkShake.java

MilkShakeClient.java

When to use Decorator Pattern

  • there are large number of different combinations or options for an object and sub-classing is not the optimal solution
  • only one-object needs, the additional functionality applied from a group of similar objects.
  • you want to change the object state and behavior at run-time

1 thought on “What is Decorator Design Pattern?”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.