Design patterns

patterns9DecoratorPattern

Path
pkg8patterns/patterns9DecoratorPattern.java
Package
pkg8patterns
Study order
9
Run
Single-file source launch
Command
java pkg8patterns/patterns9DecoratorPattern.java

There is no in-browser runner. This is the file from the curriculum, unchanged.

pkg8patterns/patterns9DecoratorPattern.java
1package pkg8patterns;2 3/*4 * Decorator (Structural)5 * ----------------------6 * INTENT: attach additional responsibilities to an object dynamically, as a7 *         flexible alternative to subclassing.8 * UML: Component <|-- ConcreteComponent and <|-- Decorator (wraps a Component).9 * PROS: add behavior at runtime; compose features; avoids subclass explosion.10 * CONS: many small wrapper objects; order can matter.11 * REAL-WORLD: java.io streams (BufferedReader wraps Reader), Collections.unmodifiableList.12 */13public class patterns9DecoratorPattern {14 15    interface Coffee { String desc(); double cost(); }16 17    static class Espresso implements Coffee {18        public String desc() { return "Espresso"; }19        public double cost() { return 2.0; }20    }21 22    // Base decorator wraps another Coffee23    static abstract class CoffeeDecorator implements Coffee {24        protected final Coffee inner;25        CoffeeDecorator(Coffee inner) { this.inner = inner; }26    }27    static class Milk extends CoffeeDecorator {28        Milk(Coffee c) { super(c); }29        public String desc() { return inner.desc() + " + Milk"; }30        public double cost() { return inner.cost() + 0.5; }31    }32    static class Sugar extends CoffeeDecorator {33        Sugar(Coffee c) { super(c); }34        public String desc() { return inner.desc() + " + Sugar"; }35        public double cost() { return inner.cost() + 0.25; }36    }37 38    public static void main(String[] args) {39        Coffee order = new Sugar(new Milk(new Espresso()));   // stack decorators40        System.out.printf("%s = $%.2f%n", order.desc(), order.cost());41    }42}