1、装饰器模式概述

装饰器模式(Decorator Pattern)动态的给一个对象添加新的功能,同时又不改变原有结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

2、装饰器模式结构

装饰器模式包含如下角色:

Component: 抽象对象

ConcreteComponent: 具体对象

Decorator: 抽象装饰类

ConcreteDecorator: 具体装饰类

java装饰模式 多次 super 打印一次 java 装饰器模式_ide

2.1、代码实现

/**
 * 抽象对象
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public interface Component {
    /**
     * 抽象方法
     */
    void operation();
}

/**
 * 具体对象
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("【ConcreteComponent】具体对象的方法实现");
    }
}

/**
 * 抽象装饰器
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public abstract class Decorator implements Component {
    protected Component component;

    public void SetComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

/**
 * 具体装饰器类 ConcreteDecoratorA
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public class ConcreteDecoratorA extends Decorator {
    /**
     * ConcreteDecoratorA 独有功能属性,区别于ConcreteDecoratorB
     */
    private String concreteDecoratorA;

    @Override
    public void operation() {
        super.operation();
        concreteDecoratorA = "我是具体装饰对象 A 的特有功能";
        System.out.println("【ConcreteDecoratorA】".concat(concreteDecoratorA));
        System.out.println("【ConcreteDecoratorA】具体装饰对象 A 的独有操作");
    }
}


/**
 * 具体装饰器实现类 B
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public class ConcreteDecoratorB extends Decorator {


    @Override
    public void operation() {
        super.operation();
        methodB();
        System.out.println("【ConcreteDecoratorB】具体装饰对象 B 的独有操作");
    }

    private void methodB() {
        System.out.println("【ConcreteDecoratorB】我是具体装饰对象 B 的特有方法");
    }
}
/**
 * 装饰器客户端测试
 *
 * @author kaifeng
 * @date 2018/12/31
 */
public class DecoratorDemo {
    public static void main(String[] args) {
        ConcreteComponent concreteComponent = new ConcreteComponent();
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();

        concreteDecoratorA.SetComponent(concreteComponent);
        concreteDecoratorB.SetComponent(concreteDecoratorA);
        concreteDecoratorB.operation();
    }
}


【ConcreteComponent】具体对象的方法实现
【ConcreteDecoratorA】我是具体装饰对象 A 的特有功能
【ConcreteDecoratorA】具体装饰对象 A 的独有操作
【ConcreteDecoratorB】我是具体装饰对象 B 的特有方法
【ConcreteDecoratorB】具体装饰对象 B 的独有操作

3、装饰器模式优点

  • 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  • 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

4、装饰器模式缺点

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

5、装饰器模式应用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
  • 不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类).