The Decorator Pattern in Java – Java中的装饰器模式

最后修改: 2018年 11月 22日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

A Decorator pattern can be used to attach additional responsibilities to an object either statically or dynamically. A Decorator provides an enhanced interface to the original object.

装饰器模式可用于静态或动态地将额外的责任附加到一个对象上。装饰器为原始对象提供一个增强的接口。

In the implementation of this pattern, we prefer composition over an inheritance – so that we can reduce the overhead of subclassing again and again for each decorating element. The recursion involved with this design can be used to decorate our object as many times as we require.

在这个模式的实现中,我们更倾向于组合而不是继承–这样我们可以减少为每个装饰元素反复子类化的开销。这种设计所涉及的递归可以用来装饰我们的对象,只要我们需要就可以了。

2. Decorator Pattern Example

2.装饰器模式示例

Suppose we have a Christmas tree object and we want to decorate it. The decoration does not change the object itself; it’s just that in addition to the Christmas tree, we’re adding some decoration items like garland, tinsel, tree-topper, bubble lights, etc.:

假设我们有一个圣诞树对象,我们想对它进行装饰。装饰并不改变对象本身,只是除了圣诞树之外,我们还增加了一些装饰品,如花环、彩带、树冠、泡沫灯等。

8poz64T

For this scenario, we’ll follow the original Gang of Four design and naming conventions. First, we’ll create a ChristmasTree interface and its implementation:

在这个场景中,我们将遵循最初的四人帮设计和命名惯例。首先,我们将创建一个ChristmasTree接口和其实现。

public interface ChristmasTree {
    String decorate();
}

The implementation of this interface will look like:

这个接口的实现将看起来像。

public class ChristmasTreeImpl implements ChristmasTree {

    @Override
    public String decorate() {
        return "Christmas tree";
    }
}

We’ll now create an abstract TreeDecorator class for this tree. This decorator will implement the ChristmasTree interface as well as hold the same object. The implemented method from the same interface will simply call the decorate() method from our interface:

我们现在将为这棵树创建一个抽象的TreeDecorator类。这个装饰器将实现ChristmasTree接口,并持有同一个对象。来自同一接口的实现方法将简单地调用我们接口中的decorate() 方法。

public abstract class TreeDecorator implements ChristmasTree {
    private ChristmasTree tree;
    
    // standard constructors
    @Override
    public String decorate() {
        return tree.decorate();
    }
}

We’ll now create some decorating element. These decorators will extend our abstract TreeDecorator class and will modify its decorate() method according to our requirement:

我们现在将创建一些装饰元素。这些装饰器将扩展我们的抽象TreeDecorator类,并根据我们的要求修改其decorate() 方法。

public class BubbleLights extends TreeDecorator {

    public BubbleLights(ChristmasTree tree) {
        super(tree);
    }
    
    public String decorate() {
        return super.decorate() + decorateWithBubbleLights();
    }
    
    private String decorateWithBubbleLights() {
        return " with Bubble Lights";
    }
}

For this case, the following is true:

对于这种情况,以下情况是真实的。

@Test
public void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
    ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
    assertEquals(tree1.decorate(), 
      "Christmas tree with Garland");
     
    ChristmasTree tree2 = new BubbleLights(
      new Garland(new Garland(new ChristmasTreeImpl())));
    assertEquals(tree2.decorate(), 
      "Christmas tree with Garland with Garland with Bubble Lights");
}

Note that in the first tree1 object, we’re only decorating it with only one Garland, while the other tree2 object we’re decorating with one BubbleLights and two Garlands. This pattern gives us this flexibility to add as many decorators as we want at runtime.

请注意,在第一个tree1对象中,我们只用一个Garland来装饰它,而另一个tree2对象我们用一个BubbleLights和两个Garlands来装饰。这种模式给了我们这种灵活性,可以在运行时添加任意多的装饰器。

4. Conclusion

4.结论

In this article, we had a look at the decorator design pattern. This is a good choice in the following cases:

在这篇文章中,我们看了一下装饰器设计模式。在以下情况下,这是一个不错的选择。

  • When we wish to add, enhance or even remove the behavior or state of objects
  • When we just want to modify the functionality of a single object of class and leave others unchanged

The full source code for this example is available over on GitHub.

这个例子的完整源代码可以在GitHub上找到