装饰器模式

装饰器模式属于结构型模式

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

装饰器模式可以为一个现有的类增加新功能,又不改变其结构,要求装饰类和被装饰类实现同一个接口,装饰类持有被装饰类的实例

模式类图

角色

  1. 抽象接口:able接口,最核心组件,被装饰类和装饰类都实现此接口
  2. 被装饰类:Source,要被装饰的类
  3. 装饰类:Decorator,持有Source类实例,装饰Source类,为Source类动态添加新功能

优点

装饰类和被装饰类相互解耦

缺点

多层的装饰比较复杂,减少装饰类的数量,可以降低系统的复杂度

模式代码实现

源码地址:https://github.com/mingyuHub/design-patterns

以打电话为例,涉及Phoneable(接口),Phone(被装饰类),Decorator(装饰类)

抽象接口

被装饰类和装饰类都实现此接口

/**
 * @author: chenmingyu
 * @date: 2019/3/1 10:20
 * @description: 手机接口
 */
public interface Phoneable {

    /**
     * 打电话
     */
    void call();
}
被装饰类

实现Phoneable接口

/**
 * @author: chenmingyu
 * @date: 2019/3/1 10:19
 * @description: 被装饰类
 */
public class Phone implements Phoneable{

    @Override
    public void call() {
        System.out.println("打电话");
    }
}
装饰类

实现Phoneable接口,持有被装饰类实例

/**
 * @author: chenmingyu
 * @date: 2019/3/1 10:26
 * @description: 装饰类
 */
public class Decorator implements Phoneable{

   private Phone phone;

   public Decorator(Phone phone) {
       this.phone = phone;
   }

    @Override
    public void call() {
        System.out.println("装饰器模式 前置功能:打电话先拨号");
        phone.call();
        System.out.println("装饰器模式 后置功能:挂断电话");
    }
}
验证
public static void main(String[] args) {
    Decorator decorator = new Decorator(new Phone());
    decorator.call();
}

输出

装饰器模式 前置功能:打电话先拨号
打电话
装饰器模式 后置功能:挂断电话

当我们要拓展一个类的功能时,可以选择使用集成或者装饰器模式,继承的实现是静态,而装饰器模式实现的是动态的,装饰器模式的缺点是会产生很多功能类似的类

参考:设计模式之禅:https://www.kancloud.cn/sstd521/design/193565

推荐阅读:23种设计模式详解