装饰图案设计

时间:2016-05-30 09:12:57

标签: java design-patterns decorator

我对模式很新,我正在研究装饰模式,我必须编写一个程序。

在线学习,我找到了一个Decorator模式的例子(它是Java伪代码):

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
    }
};

当我分析这个例子时,我意识到在过去我做了一个非常相似的模式但是以不同的方式:

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 ComponentDecorator addComponent(Component component)
        {
            this.components.add(component);
            return this;
        }

        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
    }
}

在我看来,第二个例子可以在可以使用Decorator模式的相同情况下使用,但它更灵活(例如,您可以删除或重新排序列表中的组件),所以我的问题:< / p>

  • 解决方案1(正确的装饰模式)是否比解决方案2更好?为什么?
  • 是否可以在解决方案1中添加删除实例的功能?
  • 是否可以在解决方案1中添加重新排序实例的功能?

2 个答案:

答案 0 :(得分:2)

解决方案2实际上是装饰器模式和复合模式之间的混合。

我认为解决方案1优于解决方案2,如果您想要的只是添加行为并使用解决方案1 ​​+复合模式更好,如果您还需要将多个对象用作一个。

关于使用这两种模式的更一般的答案见 Difference between the Composite Pattern and Decorator Pattern?

这是关键答案:

复合模式允许您以允许外部代码将整个结构作为单个实体查看的方式构建层次结构(例如元素树)。因此,叶实体的接口与复合实体的实体完全相同。因此,本质上是复合结构中的所有元素都具有相同的接口,即使有些是叶节点而其他元素是整个结构。用户界面通常使用这种方法来实现易于组合。

http://en.wikipedia.org/wiki/Composite_pattern

装饰器模式允许实体完全包含另一个实体,以便使用装饰器看起来与包含的实体相同。这允许装饰器修改其封装的任何内容的行为和/或内容,而不改变实体的外观。例如,您可以使用装饰器在包含元素的使用上添加日志输出,而不更改所包含元素的任何行为。

http://en.wikipedia.org/wiki/Decorator_pattern

答案 1 :(得分:1)

  

解决方案1(正确的装饰模式)是否比解决方案2更好?为什么呢?

解决方案1优于解决方案2.解决方案1遵循Gang of 4设计原样。

解决方案1 ​​

  1. 简单
  2. 与解决方案2相比,更不容易出错。您必须填写list&amp; amp;使用后清除清单(您目前没有这样做)。如果您在多个线程中使用相同的装饰器,则必须保护代码以保持内存一致性。
  3. VendingMachineDecorator 的真实示例可在本文档中找到@

    When to Use the Decorator Pattern?

      

    是否可以添加用于删除解决方案1中的实例的函数?

    是。这是可能的。您可以在抽象装饰器和具体装饰器中添加删除功能。

    public void removeStuff()
    

    您可以查看以下SE问题:

    How to remove decorated object from Decorator Pattern in Java

    Can you remove a decorator?