Decorator Method Design Patterns in Java with Example
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.
- The 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.
Remember: Certain key points are to be taken into consideration that are as follows:
- 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
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.
Step 1: Creating an interface named ‘Shape’
Example
Java
public interface Shape {
void draw();
}
|
Step 2: Create concrete classes implementing the same interface. Rectangle.java and Circle.java are as follows
Example
Java
public class Rectangle implements Shape {
@Override public void draw()
{
System.out.println( "Shape: Rectangle" );
}
}
|
Java
public 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
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape)
{
this .decoratedShape = decoratedShape;
}
public void draw() { decoratedShape.draw(); }
}
|
Step 4: Create a concrete decorator class extending the ShapeDecorator class.
Example
Java
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape)
{
super (decoratedShape);
}
@Override public void draw()
{
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape)
{
System.out.println( "Border Color: Red" );
}
}
|
Step 5: Using the RedShapeDecorator to decorate Shape objects.
Example
Java
public class DecoratorPatternDemo {
public static void main(String[] args)
{
Shape circle = new Circle();
Shape redCircle
= new RedShapeDecorator( new Circle());
Shape redRectangle
= new RedShapeDecorator( new Rectangle());
System.out.println( "Circle with normal border" );
circle.draw();
System.out.println( "\nCircle of red border" );
redCircle.draw();
System.out.println( "\nRectangle of red border" );
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
Border Color: Red
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.
Further Read: Java Design Patterns Tutorial
Last Updated :
07 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...