Skip to content

装饰器模式

一、介绍

装饰器设计模式(Decorator Pattern)也叫包装设计模式,属于结构型模式,它是作为现有的类的一个包装,允许向一个现有的对象添加新的功能,同时又不改变其结构。给对象增加功能,一般两种方式 继承或关联组合,将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为来增强功能,这个就是装饰器模式,比继承模式更加灵活。

装饰器模式可以以动态、透明的方式给单个对象添加职责,单又能不改变其结构。

jdk源码里的IO流用了大量的装饰模式

二、角色(装饰者和被装饰者有相同的超类(Component))

  • 抽象组件(Component):定义装饰方法的规范,如最初的自行车,仅仅定义了自行车的API;
  • 被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体对象,如实现了核心角色的具体自行车
  • 装饰者组件(Decorator):定义具体装饰者的行为规范, 和Component角色有相同的接口,持有组件(Component)对象的实例引用。如自行车组件 都有 名称和价格
  • 具体装饰物(ConcreteDecorator):负责给构件对象装饰附加的功能,比如 喇叭,防爆胎

jdk的装饰模式

  • 抽象组件:InputStream
  • 被装饰者(ConcreteComponent) : FileInputStream 、ByteArrayInputStream
  • 装饰者组件(Decorator):FilterInputStream
  • 具体装饰物(ConcreteDecorator):BufferedInputStream、DataInputStream

应用

//添加了Buffer缓冲功能
InputStream inputStream = new BufferedInputStream(new FileInputStream(""));

三、优缺点

  • 优点
    • 装饰模式与继承关系的目的都是要扩展对象的功能,但装饰模式可以提供比继承更多的灵活性。
    • 使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,原有代码无须改变,符合“开闭原则”
  • 缺点
    • 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂 (多层包装)
    • 增加系统的复杂度,加大学习与理解的难度

四、装饰器模式和桥接模式对比

  • 相同点都是通过封装其他对象达到设计的目的,和对象适配器也类似,有时也叫半装饰设计模式
  • 没有装饰者和被装饰者的主次区别,桥接和被桥接者是平等的,桥接可以互换,不用继承自同一个父类

五、代码

被装饰者抽象类

package com.lcy.study.design.decorator;

/**
 * @Description 自行车抽象
 * @Author lcy
 * @Date 2021/7/24 12:13
 */
public interface Bike {

    /**
     * 自行车描述信息
     * @return java.lang.String
     * @author lcy
     * @date 2021/7/24 12:13
     **/
    String getDescription();

    /**
     * 自行车价格
     * @return long
     * @author lcy
     * @date 2021/7/24 12:14
     **/
    long getPrice();

}

具体被装饰者

package com.lcy.study.design.decorator;

/**
 * @Description 具体被装饰者
 * @Author lcy
 * @Date 2021/7/24 12:14
 */
public class BigBike implements Bike {

    @Override public String getDescription(){
        return "大号自行车";
    }

    @Override public long getPrice(){
        return 100;
    }
}

装饰者组件类

package com.lcy.study.design.decorator;

/**
 * @Description 自行车装饰者组件
 * @Author lcy
 * @Date 2021/7/24 12:15
 */
public class BikeDecorator implements Bike {

    @Override public String getDescription(){
        return null;
    }

    @Override public long getPrice(){
        return 0;
    }
}

具体被装饰者

package com.lcy.study.design.decorator;

import lombok.AllArgsConstructor;

/**
 * @Description 大号自行车装饰者--喇叭
 * @Author lcy
 * @Date 2021/7/24 12:16
 */
@AllArgsConstructor
public class TrumpetBikeDecorator extends BikeDecorator {

    /**
     * 被装饰者
     */
    private final Bike bike;

    @Override public String getDescription(){
        return bike.getDescription() + ",装饰一个喇叭";
    }

    @Override public long getPrice(){
        return bike.getPrice() + 10;
    }

    public static void main(String[] args){
        Bike bike = new BigBike();
        bike = new TrumpetBikeDecorator(bike);
        bike = new TrumpetBikeDecorator(bike);
        System.out.println(bike.getDescription());
        System.out.println(bike.getPrice());
    }
}