Decorator Pattern



  • Decorator Pattern

    Extending an objects functionality can be done statically (at compile time) by using inheritance however it might be necessary to extend an objects functionality dynamically (at runtime) as an object is used.

    Intent

    • Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
    • Client-specified embellishment of a core object by recursively wrapping it.

    Implementation

    Class Diagram of Decorator Pattern
    Below is an interface depicting an icecream

    // Icecream.java
    public interface Icecream {
        public String makeIcecream();
    }
    

    This is the base class on which the decorators will be added.

    // SimpleIcecream.java
    public class SimpleIcecream implements Icecream {
    
        @Override
        public String makeIcecream() {
            return "Base Icecream";
        }
    }
    

    Following class is the decorator class. It is the core of the decorator design pattern. It contains an attribute for the type of interface. Instance is assigned dynamically at the creation of decorator using its constructor. Once assigned that instance method will be invoked.

    // IcecreamDecorator.java
    abstract class IcecreamDecorator implements Icecream {
    
        protected Icecream specialIcecream;
    
        public IcecreamDecorator(Icecream specialIcecream) {
            this.specialIcecream = specialIcecream;
        }
    
        public String makeIcecream() {
            return specialIcecream.makeIcecream();
        }
    }
    

    These are two decorators, concrete class implementing the abstract decorator. When the decorator is created the base instance is passed using the constructor and is assigned to the super class.

    // NuttyDecorator.java
    public class NuttyDecorator extends IcecreamDecorator {
    
        public NuttyDecorator(Icecream specialIcecream) {
            super(specialIcecream);
        }
    
        public String makeIcecream() {
            return specialIcecream.makeIcecream() + addNuts();
        }
    
        private String addNuts() {
            return " + cruncy nuts";
        }
    }
    
    // HoneyDecorator.java
    public class HoneyDecorator extends IcecreamDecorator {
    
        public HoneyDecorator(Icecream specialIcecream) {
            super(specialIcecream);
        }
    
        public String makeIcecream() {
            return specialIcecream.makeIcecream() + addHoney();
        }
    
        private String addHoney() {
            return " + sweet honey";
        }
    }
    

    Execution of the decorator pattern
    We can use as many decorators in any order we want. This excellent flexibility and changing the behaviour of an instance of our choice at runtime is the main advantage of the decorator design pattern.

    // TestDecorator.java
    public class TestDecorator {
    
        public static void main(String args[]) {
            Icecream icecream = new HoneyDecorator(new NuttyDecorator(new SimpleIcecream()));
            System.out.println(icecream.makeIcecream());
        }
    }
    

    Output

    Base Icecream + cruncy nuts + sweet honey
    

    Decorator Pattern in Java API

    The java.io classes are based on Decorator.
    Head First Design Pattern ---- Decorator Pattern

    This example also points out one of the downsides of the Decorator Pattern: designs often result in a large number of small classes that can be overwhelming.

    Reference

    JavaPapers


登录后回复
 

与 BitTiger Community 的连接断开,我们正在尝试重连,请耐心等待