Sunday, 5 January 2014

Decorator Design pattern - Implementation [Shape]

🚀 Master Core Java & Design Patterns!

Enjoying this tutorial? Subscribe to Ram N Java for clean code, real-world examples, and step-by-step programming guides.

🔔 Subscribe to Ram N Java

What is the Decorator Design Pattern?

The Decorator Pattern is a structural design pattern that lets you dynamically attach new behaviors and responsibilities to objects without modifying their existing code or affecting other objects of the same class.

Instead of relying heavily on inheritance (subclassing)—which can lead to an explosion of classes—the Decorator Pattern uses composition to wrap the original object with enhanced functionality.

The Scenario: Coloring Shapes Dynamically

Imagine you have geometric shapes like a Circle and a Rectangle. Both implement a common Shape interface with a standard draw() method that draws an uncolored shape.

Now, what if you want to create a red circle, a blue circle, or a blue rectangle? Creating separate subclasses like BlueCircle, RedCircle, BlueRectangle, and RedRectangle quickly becomes messy.

With the Decorator Pattern, you create a decorator class (such as BlueShapeDecorator) that wraps any existing shape and applies the color during execution!

Step-by-Step Implementation

1. Define the Common Component Interface

Start by defining the basic Shape interface containing the core operation:

public interface Shape {
    void draw();
}

2. Create Concrete Implementations

Implement basic shape classes (Circle and Rectangle) that draw plain shapes:

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Shape: Circle");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Shape: Rectangle");
    }
}

3. Build the Abstract Decorator

The ShapeDecorator class implements the Shape interface and holds a reference to an instance of Shape:

public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape) {
        this.decoratedShape = decoratedShape;
    }

    public void draw() {
        decoratedShape.draw();
    }
}

4. Create Concrete Decorators

Extend ShapeDecorator to add features like color enhancement:

public class BlueShapeDecorator extends ShapeDecorator {
    public BlueShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        setBlueBorder(decoratedShape);
    }

    private void setBlueBorder(Shape decoratedShape) {
        System.out.println("Color: Blue applied to shape");
    }
}

Why Use the Decorator Pattern?

  • Greater Flexibility: Enhancements can be dynamically added or removed at runtime.
  • Single Responsibility Principle: Keep complex functionalities separated into dedicated decorator classes.
  • Avoids Class Explosion: Solves the need to write endless subclasses for every combination of features.

Related Tutorials You Might Like

Deepen your software engineering and design pattern knowledge with these tutorials:



Click here to watch in Youtube : https://www.youtube.com/watch?v=b-6OtMYNkpw

Click the below Image to Enlarge
Decorator Design pattern - Implementation [Shape]


Decorator Design pattern - Implementation [Shape] - Class Diagram



































Shape.java

public interface Shape
{
void draw();
}

Circle.java

public class Circle implements Shape
{

@Override
public void draw()
{
System.out.println("Shape: Circle has been drawn");
}
}

Rectangle.java

public class Rectangle implements Shape
{

@Override
public void draw()
{
System.out.println("Shape: Rectangle has been drawn");
}
}

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape
{
protected Shape decoratedShape;

public ShapeDecorator( Shape decoratedShape )
{
this.decoratedShape = decoratedShape;
}

public void draw()
{
decoratedShape.draw();
}
}

BlueShapeDecorator.java

public class BlueShapeDecorator extends ShapeDecorator
{

public BlueShapeDecorator( Shape decoratedShape )
{
super(decoratedShape);
}

@Override
public void draw()
{
decoratedShape.draw();
setColor(decoratedShape);
}

private void setColor( Shape decoratedShape )
{
System.out.println("Color: Blue has been applied to "+decoratedShape);
}
}

DecoratorPatternDemo.java

public class DecoratorPatternDemo
{
public static void main(String[] args)
{

Shape blueCircle = new BlueShapeDecorator(new Circle());

Shape blueRectangle = new BlueShapeDecorator(new Rectangle());

System.out.println("\nCreate Blue color Circle using BlueShapeDecorator");
blueCircle.draw();

System.out.println("\nCreate Blue color Rectangle using BlueShapeDecorator");
blueRectangle.draw();
}
}

Ouput

Create Blue color Circle using BlueShapeDecorator
Shape: Circle has been drawn
Color: Blue has been applied to Circle@30c221

Create Blue color Rectangle using BlueShapeDecorator
Shape: Rectangle has been drawn
Color: Blue has been applied to Rectangle@119298d


See also:


  • Decorator Design pattern - Introduction
  • Decorator Design pattern - Real Time Example [Dosa]
  • Decorator Design pattern - Real Time Example [Ice Cream]
  • Decorator Design pattern - Real Time Example [Pizza]
  • Decorator Design pattern - Real Time Example [Car]
  • Decorator Design pattern - Class Diagram
  • Decorator Design pattern - Sequence Diagram
  • Decorator Design pattern - Implementation [Dosa]
  • Decorator Design pattern - Implementation [Pizza]
  • Decorator Design pattern - Implementation [Ice Cream]
  • Decorator Design pattern - Implementation [Car]
  • Decorator Design pattern - Key Points
  • All Design Patterns Links
  • No comments:

    Post a Comment

    Tutorials