Also known as Wrapper

Decorator

Intent

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Structure of design pattern

Decorator pattern structure

Pseudocode

// Common interface for all components.
interface DataSource is
    method writeData(data)
    method readData():data

// One of the concrete components can act as a base layer.
class FileDataSource implements DataSource is
    constructor FileDataSource(filename) { ... }

    method writeData(data) is
        Write data to file.

    method readData():data is
        Read data from file.

// All other concrete components may act as wrappers.
class DataSourceDecorator implements DataSource is
    field wrappee: DataSource

    constructor DataEncyptionDecorator(source: DataSource) is
        wrappee = source

    method writeData(data) is
        wrappee.writeData(data)

    method readData():data is
        return wrappee.readData()

// Concrete Decorators extend the functionality of a component they wrap.
class EncyptionDecorator extends DataSourceDecorator is
    method writeData(data) is
        Encrypt passed data.
        Pass the compressed data to wrappee's writeData() method.

    method readData():data is
        Get the data from wrappee's readData() method.
        Decrypt and return that data.

// You can wrap objects in several layers of decorators.
class CompressionDecorator extends DataSourceDecorator is
    method writeData(data) is
        Compress passed data
        Pass the compressed data to wrappee's writeData() method.

    method readData():data is
        Get the data from wrappee's readData() method.
        Uncompress and return that data.


// Option 1. A simple example of decorator assembly.
class Application is
    method dumbUsageExample() is
        source = new FileDataSource('somefile.dat')
        source.writeData(salaryRecords)
        // a file with plain data

        source = new CompressionDecorator(source)
        source.writeData(salaryRecords)
        // compressed file

        source = new EncyptionDecorator(source)
        source.writeData(salaryRecords)
        // compressed and encrypted file



// Option 2. Client code, which uses an external data source. SalaryManager
// neither knows not cares about data storage specifics. It receives already
// configured data source.
class SalaryManager is
    field source: DataSource

    constructor SalaryManager(source: DataSource) { ... }

    method load() is
        return source.readData()

    method save() is
        source.writeData(salaryRecords)
    // ...Other useful methods...


// Application can assemble objects with a different set of functionality using
// the same decorators at run time, depending on the configuration
// or environment.
class ApplicationConfigurator is
    method configurationExample() is
        source = new FileDataSource("salary.dat");
        if (enabledEncryption)
            source = new EncyptionDecorator(source)
        if (enabledCompression)
            source = new CompressionDecorator(source)

        logger = new SalaryLogger(source)
        salary = logger.load();
    // ...Rest of an application code.

Implementations in Different Programming Languages

Java