Decorator Design Pattern in Java with Example - GeeksforGeeks

28 Oct, 2021
The decorator design pattern allows us to dynamically add functionality and behavior to an object without affecting the behavior of other existing objects within the same class. We use inheritance to extend the behavior of the class. This takes place at compile-time, and all the instances of that class get the extended behavior.
Decorator patterns allow a user to add new functionality to an existing object without altering its structure. So, there is no change to the original class.
The decorator design pattern is a structural pattern, which provides a wrapper to the existing class.
Decorator design pattern uses abstract classes or interfaces with the composition to implement the wrapper.
Decorator design patterns create decorator classes, which wrap the original class and supply additional functionality by keeping the class methods’ signature unchanged.
Decorator design patterns are most frequently used for applying single responsibility principles since we divide the functionality into classes with unique areas of concern.
The decorator design pattern is structurally almost like the chain of responsibility pattern.
Key points to remember 
Decorator design pattern is useful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the amount of choices are more.The disadvantage of decorator design pattern is that it uses plenty of similar kind of objects (decorators)Decorator pattern is used a lot in Java IO classes, like FileReader, BufferedReader, etc.
Decorator design pattern is useful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the amount of choices are more.
The disadvantage of decorator design pattern is that it uses plenty of similar kind of objects (decorators)
Decorator pattern is used a lot in Java IO classes, like FileReader, BufferedReader, etc.
Procedure:
Create an interface.Create concrete classes implementing the same interface.Create an abstract decorator class implementing the above same interface.Create a concrete decorator class extending the above abstract decorator class.Now use the concrete decorator class created above to decorate interface objects.Lastly, verify the output
Create an interface.
Create concrete classes implementing the same interface.
Create an abstract decorator class implementing the above same interface.
Create a concrete decorator class extending the above abstract decorator class.
Now use the concrete decorator class created above to decorate interface objects.
Lastly, verify the output
Implementation:
We’re going to create a Shape interface and concrete classes implementing the Shape interface. We will then create an abstract decorator class ShapeDecorator implementing the Shape interface and having the Shape object as its instance variable.
‘Shape’ is the name of the interface‘Rectangle’ class and ‘Circle’ class will be concrete classes implementing the ‘Shape’ interface.‘ShapeDecorator’ is our abstract decorator class implementing the same ‘Shape’ interface.RedShapeDecorator is a concrete class implementing ShapeDecorator.DecoratorPatternDemo, our demo class will use RedShapeDecorator to decorate Shape objects.
‘Shape’ is the name of the interface
‘Rectangle’ class and ‘Circle’ class will be concrete classes implementing the ‘Shape’ interface.
‘ShapeDecorator’ is our abstract decorator class implementing the same ‘Shape’ interface.
RedShapeDecorator is a concrete class implementing ShapeDecorator.
DecoratorPatternDemo, our demo class will use RedShapeDecorator to decorate Shape objects.
Step 1: Creating an interface named ‘Shape’
Example
Java
// Interface named Shape// Shape.javapublic interface Shape {    void draw();}
Step 2: Create concrete classes implementing the same interface. Rectangle.java and Circle.java are as follows
Example 
Java
Java
// Class 1// Class 1 will be implementing the Shape interface // Rectangle.javapublic class Rectangle implements Shape {     // Overriding the method    @Override public void draw()    {        // /Print statement to execute when        // draw() method of this class is called        // later on in the main() method        System.out.println("Shape: Rectangle");    }}
// Circle.javapublic class Circle implements Shape {     @Override    public void draw()    {        System.out.println("Shape: Circle");    }}
 Step 3: Create an abstract decorator class implementing the Shape interface.
Example 
Java
// Class 2// Abstract class// ShapeDecorator.javapublic abstract class ShapeDecorator implements Shape {     // Protected variable    protected Shape decoratedShape;     // Method 1    // Abstract class method    public ShapeDecorator(Shape decoratedShape)    {        // This keywordd refers to current object itself        this.decoratedShape = decoratedShape;    }     // Method 2 - draw()    // Outside abstract class    public void draw() { decoratedShape.draw(); }}
 Step 4: Create a concrete decorator class extending the ShapeDecorator class.
Example 
Java
// Class 3// Concrete class extending the abstract class// RedShapeDecorator.javapublic class RedShapeDecorator extends ShapeDecorator {     public RedShapeDecorator(Shape decoratedShape)    {        super(decoratedShape);    }     @Override public void draw()    {        decoratedShape.draw();        setRedBorder(decoratedShape);    }     private void setRedBorder(Shape decoratedShape)    {      // Display message whenever function is called        System.out.println("Border Color: Red");    }}
 Step 5: Using the RedShapeDecorator to decorate Shape objects.
Example 
Java
// DecoratorPatternDemo.java // Class// Main classpublic class DecoratorPatternDemo {     // Main driver method    public static void main(String[] args)    {        // Creating an object of Shape interface        // inside the main() method        Shape circle = new Circle();         Shape redCircle            = new RedShapeDecorator(new Circle());         Shape redRectangle            = new RedShapeDecorator(new Rectangle());         // Display message        System.out.println("Circle with normal border");         // Calling the draw method over the        // object calls as created in        // above classes         // Call 1        circle.draw();         // Display message        System.out.println("\nCircle of red border");         // Call 2        redCircle.draw();         // Display message        System.out.println("\nRectangle of red border");         // Call 3        redRectangle.draw();    }}
 Step 6: Verifying the output
Output: 
Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Output explanation:  
Glancing at the decorator design pattern one can conclude out that this is often a decent choice in the following cases where
When we wish to add, enhance or perhaps remove the behavior or state of objects
When we just want to modify the functionality of a single object of the class and leave others unchanged
 
surinderdawra388
sagartomar9927
Java-Design-Patterns
Picked
Technical Scripter 2020
Java
Technical Scripter
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Initialize an ArrayList in Java
HashMap in Java with Examples
Interfaces in Java
How to iterate any Map in Java
ArrayList in Java
Multidimensional Arrays in Java
Stack Class in Java
Stream In Java
Set in Java
Overriding in Java