Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Design Patterns: Decorator Pattern

DZone's Guide to

Design Patterns: Decorator Pattern

The good, the bad, and the ugly truths about the decorator pattern in Java.

· Java Zone ·
Free Resource

How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.

The decorator pattern is one of the GoF Structural Patterns and dynamically adds logic to an object. Instead of inheritance the decorator adds functionality at run time. They introduce a huge amount of flexibility.

In the classical implementation both decorator and target object must implement the same interface. The decorator wraps the target object and adds its own behavior.

@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public class PriceDiscountDecorator implements Product {

 @Coffee
 @Any
 @Delegate
 @Inject
 private Product product;

 public String generateLabel() {
 product.setPrice(product.getPrice() * 0.5);
 return product.generateLabel();
 }
}

The implementation of the pattern relies on the delegate and decorator implementing the same interface. The delegate is wrapped and specific logic implemented for each of the interface’s methods.

The CDI container injects any available instance of a concrete instance of the Product interface into the Product member variable.

When a call is made to the generateLabel method of any Product instance, the container intercepts it. The call is delegated to the generateLabel method of the PriceDiscountDecorator decorator, where it discounts the product’s price and passes the call onto the original destination by calling the generate Label method of the destination Product instants.

Annotate with a qualifier the class you wish to decorate and the instance variable in the decorator and only instances of those classes will be injected into the decorator.

The order in which the decorators are called is specified in an XML file or by setting an Interceptor priority. Lower priorities decorators are called first.

The Good, Bad and the Ugly

The Good

It is very easy to change the behaviour without breaking legacy code.

The Bad

It may needs XML configuration (<CDI 1.1) to define the order of applying the decorators.

The Ugly

As always overuse will introduce an execution flow which is hard to follow.

How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.

Topics:
design patterns

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}