Skip to content

装饰模式

装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,主要用于在不修改原始类代码的情况下,动态地给对象添加新的职责(功能)。这种模式通过创建一个包装对象(装饰器)来包裹原有的对象,并在这个包装对象中添加新的行为或责任。装饰模式提供了一种灵活的方式来扩展对象的功能,相比通过继承来扩展更为灵活和可控制。

TIP

装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说。装饰模式比生成子类更加灵活

类图

装饰着模式

角色

  • Component(组件接口):定义一个对象接口,可以给这些对象动态添加职责。
  • ConcreteComponent(具体组件):实现了Component接口的类,即需要被装饰的基本对象。
  • Decorator(装饰器接口):继承自Component,维护一个指向Component的引用,并定义一个与Component接口一致的接口。
  • ConcreteDecorator(具体装饰器):实现Decorator接口,负责给Component添加额外的职责。

优点

  • 灵活性高:可以在运行时动态地添加功能,不需要修改原有的类。
  • 避免多层继承:通过组合而非继承来扩展功能,减少继承层次的复杂度。
  • 重用性好:装饰类可以被多次用来装饰不同的对象,也可以用于装饰其他装饰类,形成装饰链。

应用场景

  • 当需要为某些对象动态添加职责,而这些职责可以自由组合的时候。
  • 需要为一批同类对象添加不同功能,而又不想通过大量子类来实现的时候。
  • 功能需动态开启或关闭,且不想使用复杂的条件语句来控制的时候。

示例

假设有一个简单的文本编辑器,基础功能是显示文本。现在要为文本增加加粗、斜体、下划线等格式化功能,而不修改原始的文本显示类。这里就可以使用装饰模式,定义一个TextDisplay作为Component,然后为每种格式创建一个Decorator(如BoldDecoratorItalicDecorator),通过叠加这些装饰器,动态地给文本增加多种格式。

首先,我们定义一个基础接口TextComponent,它是所有文本组件(包括原始文本和装饰器)的基类:

java
// Component: 基础文本组件接口
interface TextComponent {
    String display(); // 显示文本的方法
}

接下来,实现这个接口的基础文本显示类PlainText,即具体的组件ConcreteComponent

java
// ConcreteComponent: 具体的文本组件 - 简单文本
class PlainText implements TextComponent {
    private final String text;

    public PlainText(String text) {
        this.text = text;
    }

    @Override
    public String display() {
        return text;
    }
}

定义装饰器接口TextDecorator,它也实现了TextComponent接口,并包含一个对TextComponent的引用,用于维持装饰器和被装饰对象的关系:

java
// Decorator: 文本装饰器接口
abstract class TextDecorator implements TextComponent {
    protected TextComponent textComponent; // 在TextDecorator类中声明textComponent为成员变量

    public TextDecorator(TextComponent textComponent) {
        this.textComponent = textComponent; // 这里将构造函数参数赋值给成员变量
    }
}

然后,创建具体的装饰器类,比如BoldDecorator(加粗装饰器)和ItalicDecorator(斜体装饰器):

java
// ConcreteDecorator: 加粗装饰器
class BoldDecorator extends TextDecorator {
    public BoldDecorator(TextComponent textComponent) {
        super(textComponent);
    }

    @Override
    public String display() {
        return "<b>" + textComponent.display() + "</b>";
    }
}

// ConcreteDecorator: 斜体装饰器
class ItalicDecorator extends TextDecorator {
    public ItalicDecorator(TextComponent textComponent) {
        super(textComponent);
    }

    @Override
    public String display() {
        return "<i>" + textComponent.display() + "</i>";
    }
}

最后,演示如何使用这些类来动态地给文本添加格式:

java
public class DecoratorPatternDemo {
    public static void main(String[] args) {
        // 创建一个原始文本对象
        TextComponent plainText = new PlainText("Hello, World!");

        // 使用装饰器给文本加粗
        TextComponent boldText = new BoldDecorator(plainText);

        // 进一步使用装饰器给文本添加斜体
        TextComponent italicAndBoldText = new ItalicDecorator(boldText);

        // 输出最终的文本效果
        System.out.println(italicAndBoldText.display()); // 输出: <i><b>Hello, World!</b></i>
    }
}

这段代码展示了如何使用装饰模式来动态地增强对象的功能,而无需修改原始类的代码。通过组合多个装饰器,我们可以灵活地给文本添加多种格式,体现了装饰模式的灵活性和扩展性。

最终显示

<i><b>Hello, World!</b></i>

Released under the MIT License.