DEV Community

Cover image for Java Quickie. Decorator Pattern
Tristan Elliott
Tristan Elliott

Posted on • Edited on

Java Quickie. Decorator Pattern

Introduction

  • This series is going to be dedicated to the basic understanding of Java. When ever I find myself asking, "How does this work ?". I will create a blog post and put it here. This series will not be in order so feel free to read what ever post you find most relevant.

GitHub link

  • All the code can be found on GitHub, HERE

YouTube version

  • The YouTube version of this blog post can be found HERE

The Decorator Pattern

  • The decorator pattern is a structural pattern and structural patterns are concerned with how classes and objects are composed to form larger structures. This pattern allows us to attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality. Technical jargin aside, this pattern gives us a new way to create classes and objects.
  • When we implement the decorator pattern we will follow 5 steps

1) Create an interface

  • This step and step 3 are the most important steps, so read closely. This step is important because we will be exploiting polymorphism with the interface we are going to create. It is also just proper OOP to program to an interface and not a implementation. So when we create the interface, make sure to think what methods should be implemented. While we can go and change this interface later on, it is best that we abide by the open/closed principle and try not to directly change it.
  • For this example we will be creating an interface called Button and it will have one method called click(). Every decoration object that we create will have this method.
public interface Button {
    public String click();
}

Enter fullscreen mode Exit fullscreen mode

2) Create the base concrete classes

  • This part is pretty easy, we literally create base classes. This would be a class that does not need any extra functionality. Think of a button that only does the base task.
public class BasicButton implements Button{
    @Override
    public String click() {
        // TODO Auto-generated method stub

        return "BASE ACTION BUTTON";    
    }
}

Enter fullscreen mode Exit fullscreen mode

3) Create abstract decorator

  • As I mentioned earlier this is the other important step, this step is what will give our objects the recursive functionality. All we have to do is to create a abstract class(abstract classes make sure the class can only be extended not implemented) and have it implement the Button interface from step one. The implementation of the Button interface will automatically make our code implement the click method. However, the true magic of this class lies in the instance variable and the constructor. This class will have one instance variable, which we will call baseButton and it will be of type Button. The constructor will take in a object of type Button and then assign it to the instance variable. Now I call this part magic because it will allow us to create the decorator pattern look of a class inside a class, inside a class, inside a class.... Then lastly we use the click method to forward the methods calls to the baseButton variable.
abstract class ButtonDecorator implements Button{
    private Button baseButton;

    public ButtonDecorator (Button newButton) {
        this.baseButton = newButton;
    }

    @Override
    public String click() {
        return baseButton.click();
    }

}
Enter fullscreen mode Exit fullscreen mode

4) Implement the decorator

  • In this part we create a class and have it extends the abstract class from step 3 (ButtonDecorator). All we have to do is implement a matching constructor and to add extra functionality we simply override the click() method.
public class AddedFunctionality extends ButtonDecorator {

    public AddedFunctionality (Button newButton) {
        super(newButton);
    }

    @Override
    public String click() {
        System.out.println(super.click() + extraFunctionality());
        return super.click() + " --> "+ extraFunctionality();
    }

    public String extraFunctionality() {
        return " EXTRA FUNCTIONALITY";
    }

}

Enter fullscreen mode Exit fullscreen mode
  • The super.click() is how we can still call the super classed click() method.

5) Put it in action

    public static void main(String [] args) {
        Button button = new BasicButton();
        Button decoratedButton = new AddedFunctionality (button);
        moreActionButton.click();
    }


Enter fullscreen mode Exit fullscreen mode

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.

Top comments (0)