lundi 30 mai 2016

Decorator Pattern design

I'm pretty new with patterns and I'm studying Decorator Pattern for a program I have to write.

Studying online, I found an example of a Decorator Pattern (it is Java pseudo-code):

class Solution1
{
    static interface Component 
    { 
        void doStuff(); 
    }

    static class MyComponent implements Component 
    {
        public void doStuff()
        {
            // ...
        }
    }

    static class ComponentDecorator implements Component  // This is the Decorator pattern.
    { 
        private final Component component;

        public ComponentDecorator(Component component) 
        {
            this.component = component;
        }

        public void doStuff()
        {
            this.component.doStuff();
        }
    }

    static class ComponentDecorator1 extends ComponentDecorator 
    {
        public ComponentDecorator1(Component component) 
        {
            super(component);
        }

        private void doExtraStuff1()
        {
            // ...
        }

        public void doStuff()
        {
            super.doStuff();
            doExtraStuff1();
        }
    }

    static class ComponentDecorator2 extends ComponentDecorator 
    {
        public ComponentDecorator2(Component component) 
        {
            super(component);
        }

        private void doExtraStuff2()
        {
            // ...
        }

        public void doStuff()
        {
            super.doStuff();
            doExtraStuff2();
        }
    }

    public static void main(String[] args)
    {
        MyComponent         c   = new MyComponent();
        ComponentDecorator1 cd1 = new ComponentDecorator1(c);
        ComponentDecorator2 cd2 = new ComponentDecorator2(cd1);

        cd2.doStuff(); // Executes Component.doStuff, ComponentDecorator1.doExtraStuff1, ComponentDecorator2.doExtraStuff2
    }
};

When I analyzed the example, I realized that in the past I made a very similar pattern but in different way:

import java.util.*;

class Solution2
{
    static interface Component 
    { 
        void doStuff(); 
    }

    static class MyComponent implements Component 
    {
        public void doStuff()
        {
            // ...
        }
    }

    static class ComponentDecorator implements Component  // This is NOT the Decorator pattern!
    { 
        private final List<Component> components = new ArrayList<Component>();

        public ComponentDecorator() 
        {
        }

        public void addComponent(Component component)
        {
            this.components.add(component);
        }

        public void removeComponent(Component component) // Can Decorator do this?
        {
            // ...
        }

        public void doStuff()
        {
            for(Component c : this.components) c.doStuff();
        }
    }

    static class ComponentDecorator1 implements Component 
    {
        public ComponentDecorator1() 
        {
        }

        private void doExtraStuff1()
        {
            // ...
        }

        public void doStuff()
        {
            doExtraStuff1();
        }
    }

    static class ComponentDecorator2 implements Component 
    {
        public ComponentDecorator2() 
        {
        }

        private void doExtraStuff2()
        {
            // ...
        }

        public void doStuff()
        {
            doExtraStuff2();
        }
    }

    public static void main(String[] args)
    {
        ComponentDecorator cd  = new ComponentDecorator();
        cd.addComponent(new MyComponent());
        cd.addComponent(new ComponentDecorator1());
        cd.addComponent(new ComponentDecorator2());

        cd.doStuff(); // Executes MyComponent.doStuff, ComponentDecorator1.doExtraStuff1, ComponentDecorator2.doExtraStuff2
    }
}

In my opinion, the second example can be used in same situations where a Decorator Pattern can be used, but it's more flexible (you may, by example, remove or reorder the components in the list), so my questions:

  • Is solution 1 (correct Decorator Pattern) better than solution 2? Why?
  • Is it possible to add functions for removing instances in solution 1?
  • Is it possible to add functions for reordering instances in solution 1?

Aucun commentaire:

Enregistrer un commentaire