Decorator Design Pattern
Image by upklyak on Freepik

Decorator Design Pattern

Decorator is a structural design pattern that allows you to dynamically attach new functionality to an object at runtime through Composition. Additionally, other instances of that class will not be affected by the changes.

Implementation

As the holiday season is upon us, we are required to come up with a solution for calculating the price of decor setups for an Events Decor business. We can restrict our scope to balloon garlands, a feature that is commonplace in events. Customer needs may vary according to the themes they are going for, the type of event; baby showers, weddings, birthdays, etc.

The garlands could conceivably be; a simple monochromatic balloon setup, an anime themed setup with a Goku blowup as the center piece, a jungle colored balloon setup with vines incorporated and many more.

Creating classes to meet each customization will lead to cluttering your code with an endless list of smaller classes.

This problem lends itself well to implementing Decorator. We have a base class BalloonGarland , which can be decorated with extra add-ons. By using the Decorator pattern, you can extend the functionality of the BalloonGarland class at runtime, based upon the customer's request.


Let's look at how we can come up with these two garlands; A jungle themed birthday party setup that also includes vines and a baby shower setup with pastel colored balloons and additional lettering.

The implementation is quite straight forward.

  • First we create an abstract base class.
  • Then we add decorator classes for the extra functionality.

Our base class will look like this:

public abstract class BalloonGarland {

    protected String description = "Balloon Garland";

    public String getDescription(){
        return description;
    }

    public abstract BigDecimal price();
}        

For simplicity we have only 2 fields, description and price.

Let's add a convenient class to allow us to define the type of balloons we will have:

public class MulticolouredBalloonGarland extends BalloonGarland{


    public MulticolouredBalloonGarland(String desc) {
        description = desc;
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(120.40);
    }

}        

Now for the decorators:

We will have a base class which will provide common functionality for the other additional decorators.

public abstract class BalloonGarlandDecorator  extends BalloonGarland {

    public abstract BigDecimal price();
}
        

The vines decorator

public class VinesDecorator extends BalloonGarlandDecorator {
    public BalloonGarland balloonGarland;

    public VinesDecorator(BalloonGarland balloonGarland) {
        this.balloonGarland = balloonGarland;
    }

    @Override
    public String getDescription() {
        return balloonGarland.getDescription() + ", with vines";
    }

    @Override
    public BigDecimal price() {
        return balloonGarland.price().add(BigDecimal.valueOf(20.50));
    }
}        

The decorator that will handle lettering:

public class LetteringDecorator extends BalloonGarlandDecorator {

    public BalloonGarland currentGarland;

    public LetteringDecorator(BalloonGarland balloonGarland) {
        currentGarland = balloonGarland;
    }

    @Override
    public String getDescription() {
        return currentGarland.getDescription() + " , with lettering";
    }

    @Override
    public BigDecimal price() {
        return currentGarland.price().add(BigDecimal.valueOf(50.40));
    }
}        

Now bringing everything together:

public static void main(String[] args) {
    BalloonGarland extravagantGarland = new MulticolouredBalloonGarland("Jungle Themed Balloon Garland");
    System.out.printf("The price of a %s is $%.2f %n", extravagantGarland.getDescription(), extravagantGarland.price());

    BalloonGarland simpleGarland = new MulticolouredBalloonGarland("Pastel Colours Balloon Garland");
    System.out.printf("The price of a %s is $%.2f %n", simpleGarland.getDescription(), simpleGarland.price());

    System.out.println();
    //add decorations
    extravagantGarland = new VinesDecorator(extravagantGarland);
    System.out.printf("The price of a %s is $%.2f %n", extravagantGarland.getDescription(), extravagantGarland.price());

    simpleGarland = new LetteringDecorator(simpleGarland);
    System.out.printf("The price of a %s is $%.2f %n", simpleGarland.getDescription(), simpleGarland.price());

}        

The output will be:

The price of a Jungle Themed Balloon Garland is $120.40 
The price of a Pastel Colours Balloon Garland is $120.40 

The price of a Jungle Themed Balloon Garland, with vines is $140.90 
The price of a Pastel Colours Balloon Garland , with lettering is $170.80         

The two garlands are decorated at runtime and the prices are updated with each decoration.

Here are a few pros and cons of using the Decorator Pattern

Pros

  • Flexibility to add or remove functionality at runtime.
  • Decorator adheres to Open-closed and single responsibility principles of SOLID


Cons

  • It uses a lot of similar kind of objects(the decorators).

The entire code sample can be found here Balloon Service

要查看或添加评论,请登录

David Muchai的更多文章

  • Spring Framework's WebClient

    Spring Framework's WebClient

    With the gaining popularity of reactive programming among the Spring community, the WebClient interface provides a…

  • Builder Design Pattern

    Builder Design Pattern

    'Builder' is a creational design pattern that handles creating instances of complex objects. Once you exceed 4 or 5…

    1 条评论
  • Design Patterns For Software Development

    Design Patterns For Software Development

    Design patterns are reusable and proven solutions to common problems that arise during the design and development of…

社区洞察

其他会员也浏览了