YouTip LogoYouTip

Decorator Pattern

# Decorator Pattern The Decorator Pattern allows you to add new functionality to an existing object without altering its structure. This type of design pattern is a structural pattern and acts as a wrapper around an existing class. The Decorator Pattern involves wrapping objects in decorator classes to dynamically modify their behavior. This pattern creates a decorator class to wrap the original class while providing additional functionality, keeping the class method signatures intact. We will demonstrate the usage of the Decorator Pattern through the following example. In this example, we will decorate a shape with different colors without changing the shape class. ## Overview ### Intent Dynamically add additional responsibilities to an object without changing its structure. The Decorator Pattern provides a flexible alternative to inheritance for extending functionality. ### Problem It Solves * Avoids introducing static characteristics through inheritance, especially when the number of subclasses grows rapidly. * Allows for dynamic addition or modification of object functionality at runtime. ### Use Cases * When you need to extend the functionality of a class without adding a large number of subclasses. * When you need to dynamically add or remove functionality from an object. ### Implementation Approach * **Define the Component Interface**: Create an interface that specifies the standard for objects to which responsibilities can be dynamically added. * **Create Concrete Components**: Implement the interface with concrete classes that provide the basic functionality. * **Create the Abstract Decorator**: Implement the same interface, holding a reference to a component interface, allowing for dynamic addition of functionality at any time. * **Create Concrete Decorators**: Extend the abstract decorator to add additional responsibilities. ### Key Code * **Component Interface**: Defines the standard for objects that can be decorated. * **ConcreteComponent Class**: A concrete class that implements the Component interface. * **Decorator Abstract Class**: Implements the Component interface and contains a reference to a Component interface. * **ConcreteDecorator Class**: Extends the Decorator class, adding extra functionality. ### Application Examples 1. **Sun Wukong's 72 Transformations**: Sun Wukong (ConcreteComponent) gains new abilities through transformations (Decorator). 2. **Decorating a Painting with a Frame**: A painting (ConcreteComponent) can be enhanced for display by adding glass (ConcreteDecorator) and a frame (ConcreteDecorator). ### Advantages * **Low Coupling**: The decorator and the decorated class can change independently without affecting each other. * **Flexibility**: Functionality can be dynamically added or removed. * **Alternative to Inheritance**: Provides a way to extend object functionality outside of inheritance. ### Disadvantages * **Complexity**: Multiple layers of decoration can lead to increased system complexity. ### Usage Recommendations * Consider using the Decorator Pattern when you need to dynamically extend functionality. * Keep the interfaces of decorators and concrete components consistent to ensure flexibility. ### Considerations * The Decorator Pattern can replace inheritance, but it should be used cautiously to avoid over-decoration leading to system complexity. ### Structure **The Decorator Pattern includes the following core roles:** * **Abstract Component (Component)**: Defines the common interface or abstract class for the original object and the decorator objects. It can be the parent class or interface of the concrete component class. * **Concrete Component (Concrete Component)**: The original object being decorated. It defines the object to which new functionality needs to be added. * **Abstract Decorator (Decorator)**: Inherits from the abstract component. It contains an abstract component object and defines the same interface as the abstract component. It can also hold other decorator objects through composition. * **Concrete Decorator (Concrete Decorator)**: Implements the interface of the abstract decorator and is responsible for adding new functionality to the abstract component. Concrete decorators typically execute their own operations before or after calling the methods of the original object. The Decorator Pattern achieves multi-level functionality enhancement by nesting and wrapping multiple decorator objects. Each concrete decorator class can selectively add new functionality while maintaining the consistency of the object interface. ## Implementation We will create a _Shape_ interface and concrete classes that implement the _Shape_ interface. Then, we will create an abstract decorator class _ShapeDecorator_ that implements the _Shape_ interface and uses a _Shape_ object as its instance variable. _RedShapeDecorator_ is a concrete class that implements _ShapeDecorator_. The _DecoratorPatternDemo_ class uses _RedShapeDecorator_ to decorate _Shape_ objects. !(#) ### Step 1 Create an interface: ## Shape.java public interface Shape{void draw(); } ### Step 2 Create concrete classes implementing the interface. ## Rectangle.java public class Rectangle implements Shape{ @Override public void draw(){System.out.println("Shape: Rectangle"); }} ## Circle.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. ## ShapeDecorator.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 concrete decorator classes extending the _ShapeDecorator_ class. ## RedShapeDecorator.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 Use _RedShapeDecorator_ to decorate _Shape_ objects. ## DecoratorPatternDemo.java public class DecoratorPatternDemo{public static void main(String[]args){Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); //Shape redCircle = new RedShapeDecorator(new Circle());//Shape redRectangle = new RedShapeDecorator(new Rectangle());System.out.println("Circle with normal border"); circle.draw(); System.out.println("n Circle of red border"); redCircle.draw(); System.out.println("n Rectangle of red border"); redRectangle.draw(); }} ### Step 6 Execute the program, and the output will be: Circle with normal border Shape: CircleCircle of red border Shape: CircleBorder Color: RedRectangle of red border Shape: RectangleBorder Color: Red
← Facade PatternComposite Pattern β†’