Design Pattern

Decorator Pattern

Clean Java-only production-ready implementation.


You need to add responsibilities to an object dynamically without modifying the original class. Subclassing every combination is explosive (BaseLogger + TimestampLogger + JSONLogger + EncryptionLogger = 2^N classes). Decorator wraps the original and adds behavior transparently.

// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A database stream writer wrapping files with Compression and Encryption
// layers at runtime.
//
// WHERE THE DECORATOR FITS IN:
// DataStream is the Component. FileDataStream is the Concrete Component.
// DataStreamDecorator is the base Decorator class wrapped by
// EncryptionDecorator.
// ────────────────────────────────────────────────────────────────────────────
// --- Component ---
interface Logger {
    void log(String message);
}

// --- Concrete component ---
class SimpleLogger implements Logger {
    public void log(String message) {
        System.out.println(message);
    }
}

// --- Base decorator ---
abstract class LoggerDecorator implements Logger {
    protected final Logger wrapped;

    public LoggerDecorator(Logger wrapped) { this.wrapped = wrapped; }

    public void log(String message) {
        wrapped.log(message);  // Default: delegate
    }
}

// --- Concrete decorators ---
class TimestampDecorator extends LoggerDecorator {
    public TimestampDecorator(Logger wrapped) { super(wrapped); }

    public void log(String message) {
        super.log("[2025-01-15 10:30:00] " + message);
    }
}

class JsonDecorator extends LoggerDecorator {
    public JsonDecorator(Logger wrapped) { super(wrapped); }

    public void log(String message) {
        super.log("{"message": "" + message + "", "level": "INFO"}");
    }
}

class EncryptionDecorator extends LoggerDecorator {
    public EncryptionDecorator(Logger wrapped) { super(wrapped); }

    public void log(String message) {
        String encrypted = "encrypted(" + message + ")";
        super.log(encrypted);
    }
}

public class Main {
    public static void main(String[] args) {
        // Compose decorators at runtime
        Logger logger = new TimestampDecorator(
                          new JsonDecorator(
                            new EncryptionDecorator(
                              new SimpleLogger())));

        logger.log("User login successful");
        // Output: [2025-01-15 10:30:00] {"message": "encrypted(User login successful)", "level": "INFO"}
    }
}