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
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Code of Shadows: Master Shifu and Po Use Functional Java to Solve the Decorator Pattern Mystery
  • Decorating Microservices
  • Decorator Pattern to Solve Integration Scenarios in Existing Systems

Trending

  • Avoiding AI Debt as a Team
  • Part 1: Building Governed MCP Tool Services With Quarkus LangChain4j and Goose
  • Taming Parameter Sniffing in SQL Server 2022 With PSP Optimization
  • Replay, Scheduling, and Throttling: Engineering a Self-Service Kafka Streaming Tool at Scale

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

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
·
Dec. 20, 16 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
17.7K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

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

  • Code of Shadows: Master Shifu and Po Use Functional Java to Solve the Decorator Pattern Mystery
  • Decorating Microservices
  • Decorator Pattern to Solve Integration Scenarios in Existing Systems

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

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 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook