Cui
Cui The he of cuizhanming.com.

Decorator Pattern

Decorator Pattern

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.

What is decorator pattern?

  • Wikipedia ```java // The Window interface class public interface Window { void draw(); // Draws the Window String getDescription(); // Returns a description of the Window }

// Implementation of a simple Window without any scrollbars class SimpleWindow implements Window { @Override public void draw() { // Draw window } @Override public String getDescription() { return “simple window”; } }

// abstract decorator class - note that it implements Window abstract class WindowDecorator implements Window { private final Window windowToBeDecorated; // the Window being decorated

1
2
3
4
5
6
7
8
9
10
11
public WindowDecorator (Window windowToBeDecorated) {
    this.windowToBeDecorated = windowToBeDecorated;
}
@Override
public void draw() {
    windowToBeDecorated.draw(); //Delegation
}
@Override
public String getDescription() {
    return windowToBeDecorated.getDescription(); //Delegation
} }

// The first concrete decorator which adds vertical scrollbar functionality class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window windowToBeDecorated) { super(windowToBeDecorated); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public void draw() {
    super.draw();
    drawVerticalScrollBar();
}

private void drawVerticalScrollBar() {
    // Draw the vertical scrollbar
}

@Override
public String getDescription() {
    return super.getDescription() + ", including vertical scrollbars";
} }

// The second concrete decorator which adds horizontal scrollbar functionality class HorizontalScrollBarDecorator extends WindowDecorator { public HorizontalScrollBarDecorator (Window windowToBeDecorated) { super(windowToBeDecorated); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public void draw() {
    super.draw();
    drawHorizontalScrollBar();
}

private void drawHorizontalScrollBar() {
    // Draw the horizontal scrollbar
}

@Override
public String getDescription() {
    return super.getDescription() + ", including horizontal scrollbars";
} } ```

V.S. chain of responsibility pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.util.Arrays;
import java.util.EnumSet;
import java.util.function.Consumer;

@FunctionalInterface
public interface Logger {
    public enum LogLevel {
        INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;

        public static LogLevel[] all() {
            return values();
        }
    }

    abstract void message(String msg, LogLevel severity);

    default Logger appendNext(Logger nextLogger) {
        return (msg, severity) -> {
            message(msg, severity);
            nextLogger.message(msg, severity);
        };
    }

    static Logger logger(LogLevel[] levels, Consumer<String> writeMessage) {
        EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
        return (msg, severity) -> {
            if (set.contains(severity)) {
                writeMessage.accept(msg);
            }
        };
    }

    static Logger consoleLogger(LogLevel... levels) {
        return logger(levels, msg -> System.err.println("Writing to console: " + msg));
    }

    static Logger emailLogger(LogLevel... levels) {
        return logger(levels, msg -> System.err.println("Sending via email: " + msg));
    }

    static Logger fileLogger(LogLevel... levels) {
        return logger(levels, msg -> System.err.println("Writing to Log File: " + msg));
    }

    public static void main(String[] args) {
        // Build an immutable chain of responsibility
        Logger logger = consoleLogger(LogLevel.all())
                .appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
                .appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR));

        // Handled by consoleLogger since the console has a loglevel of all
        logger.message("Entering function ProcessOrder().", LogLevel.DEBUG);
        logger.message("Order record retrieved.", LogLevel.INFO);

        // Handled by consoleLogger and fileLogger since filelogger implements Warning & Error
        logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING);
        logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR);

        // Handled by consoleLogger and emailLogger as it implements functional error
        logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL_ERROR);

        // Handled by consoleLogger and emailLogger
        logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE);
    }
}

comments powered by Disqus