DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Decorating Microservices
  • Decorator Pattern to Solve Integration Scenarios in Existing Systems

Trending

  • A Complete Guide to Modern AI Developer Tools
  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • A Guide to Developing Large Language Models Part 1: Pretraining
  • Transforming AI-Driven Data Analytics with DeepSeek: A New Era of Intelligent Insights

The Decorator Builder

The Decorator Pattern is useful, but the stacking of Decorators can make your code hard to read. Combine the Builder and Decorator patterns for more synergy.

By 
Nehme Bilal user avatar
Nehme Bilal
·
Dec. 20, 16 · Tutorial
Likes (27)
Comment
Save
Tweet
Share
17.1K Views

Join the DZone community and get the full member experience.

Join For Free

In my previous article, Is Inheritance Dead?, I discussed the advantages of using the decorator pattern over inheritance. While most readers agree that the decorator pattern (and composition in general) has many advantages over inheritance, composing decorators came up several times as one of the main pain-points of using the decorator pattern. In this short article, I will present a simple approach to overcome this difficulty.

Composing Decorators

Recall that the decorator pattern is designed in a way that multiple decorators can be stacked on top of each other, each adding a new functionality (see Is Inheritance Dead? for more details). Stacking decorators and choosing their order (referred to as composing decorators) can be difficult to implement and can lead to code that is difficult to read and maintain.

To illustrate, let’s consider the email service example discussed in Is Inheritance Dead? We can create an instance of IEmailService that is thread-safe, implements retries, has a cache and has verbose logging by composing decorators as follows:

IEmailService emailService = new EmailServiceCacheDecorator(
  new EmailServiceLoggingDecorator(new EmailServiceRetryDecorator(
    new EmailServiceLoggingDecorator(new EmailServiceThreadSafetyDecorator(
  new EmailService())))));

As you can see, the resulting code can be a bit overwhelming. In addition, applying decorators in the wrong order can lead to incorrect behavior.

In contrast to a hierarchy issue, such as the exploding class hierarchy issue discussed in my previous post, the difficulty of composing decorators can be easily overcome by organizing the code a little bit differently.

The Decorator Builder

The decorator builder is not a new pattern, it's just a way of using the builder pattern to make composing decorators easier. This is particularly useful for public API's where simplicity is crucial.

The code below illustrates a decorator builder for the email service API discussed in the previous section:

public class EmailServiceBuilder
{
    private IEmailService emailService = new EmailService();

    public EmailServiceBuilder synchronize() {
        emailService = new EmailServiceThreadSafetyDecorator(emailService);
        return this;
    }

    public EmailServiceBuilder retry() {
        emailService = new EmailServiceRetryDecorator(emailService);
        return this;
    }

    public EmailServiceBuilder log() {
        emailService = new EmailServiceLoggingDecorator(emailService);
        return this;
    }

    public EmailServiceBuilder cache() {
        emailService = new EmailServiceCacheDecorator(emailService);
        return this;
    }

    public IEmailService build() {
        IEmailService es = emailService;

        // Reset the builder so it can be reused
        emailService = new EmailService();

        return es;
    }
}


Using this decorator builder, the same instance of IEmailService discussed above can be created as follows:

IEmailService emailService = new EmailServiceBuilder().synchronize()
  .log().retry().log().cache().build();


Notice that the resulting code is easier to read, is verbose and less error prone than the original code. Furthermore, the order in which the decorators are added to the builder is the same as the order in which the decorators will be executed at runtime. In fact, without the builder, the order was inversed, which can cause confusion.

Conclusion

Composing decorators is not really a drawback of the decorator pattern. In fact, like any other Java code, it can be dramatically simplified by organizing the code a little bit differently (e.g. by using more functions and classes). In this article, we used the builder pattern to simplify composing decorators. As shown, the resulting code is simple and easy to maintain.

Decorator pattern

Opinions expressed by DZone contributors are their own.

Related

  • Decorating Microservices
  • Decorator Pattern to Solve Integration Scenarios in Existing Systems

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: