Understanding the Decorator Pattern in Java: Core Roles and Practical Implementation
This article explains the Decorator design pattern in Java, detailing its four core participants—Component, ConcreteComponent, Decorator, and ConcreteDecorator—through UML diagrams and complete code examples, and also illustrates how Java’s InputStream hierarchy uses FilterInputStream as a real‑world decorator.
The Decorator pattern is a structural design pattern that allows behavior to be added to individual objects dynamically without affecting other objects of the same class.
It consists of four essential roles: the Component interface, ConcreteComponent classes that implement the core functionality, an abstract Decorator class that also implements the Component interface and holds a reference to a Component, and ConcreteDecorator classes that extend the Decorator to add extra behavior.
A UML class diagram (not shown here) visualises these relationships, where the Decorator and ConcreteDecorator can be stacked to achieve multiple layers of augmentation.
public interface Car { void run(); }
public class BenzCar implements Car { @Override public void run() { System.out.println("奔驰开车了!"); } } public class BmwCar implements Car { @Override public void run() { System.out.println("宝马开车了!"); } } public class TeslaCar implements Car { @Override public void run() { System.out.println("特斯拉开车了!"); } }
public class CarDecorator implements Car { protected Car decoratedCar; public CarDecorator(Car decoratedCar) { this.decoratedCar = decoratedCar; } @Override public void run() { decoratedCar.run(); } }
public class AutoCarDecorator extends CarDecorator { public AutoCarDecorator(Car decoratedCar) { super(decoratedCar); } @Override public void run() { decoratedCar.run(); autoRun(); } private void autoRun() { System.out.println("开启自动驾驶"); } } public class FlyCarDecorator extends CarDecorator { public FlyCarDecorator(Car decoratedCar) { super(decoratedCar); } @Override public void run() { decoratedCar.run(); fly(); } private void fly() { System.out.println("开启飞行汽车模式"); } }
public class Client { public static void main(String[] args) { Car benzCar = new BenzCar(); Car bmwCar = new BmwCar(); Car teslaCar = new TeslaCar(); CarDecorator autoBenzCar = new AutoCarDecorator(benzCar); CarDecorator flyAutoBmwCar = new FlyCarDecorator(new AutoCarDecorator(bmwCar)); benzCar.run(); bmwCar.run(); teslaCar.run(); autoBenzCar.run(); flyAutoBmwCar.run(); } }
Beyond the illustrative car example, the JDK itself uses the Decorator pattern: various concrete InputStream subclasses (e.g., FileInputStream , ByteArrayInputStream ) inherit from the abstract InputStream , while FilterInputStream acts as a decorator that holds an InputStream instance and adds functionality such as buffering ( BufferedInputStream ) or data‑type reading ( DataInputStream ).
This demonstrates how the Decorator pattern provides a flexible mechanism for extending behavior without modifying existing code, making it a fundamental technique in object‑oriented design.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.