设计模式之装饰器模式

一、介绍

装饰器模式(Decoration Pattern),属于结构型设计模式 ,用于在不改变现有对象 的基础上,对该对象的方法动态 地添加新的功能,实现对该对象原有方法的增强

装饰器模式的设计思想是将对象的核心功能附加功能独立开来。核心功能由现有对象提供,附加功能由装饰器提供。

装饰器的实现思路是存在一个抽象的装饰器类 ,该装饰器类用于对现有的对象进行包装,然后通过该装饰器的具体子类对包装的类的方法进行增强。推而论之,在存在多个装饰器具体子类的情况下,可以动态地对现有对象随心所欲进行嵌套包装,对现有对象进行包装后,可以在已包装基础上进行多层嵌套包装

二、主要角色

在装饰器模式中,主要包含以下四个角色:

  • 核心组件抽象接口(Component)

规定了被装饰对象的行为。

  • 核心组件具体实现(ComponentImpl)

实现核心组件抽象接口,对接口规定的行为进行具体实现。

  • 抽象装饰器(AbsDecoration)

通用的装饰ComponentImpl的装饰器,该装饰器必须包含一个以被装饰对象为参数的构造方法。

该装饰器设定为抽象类的原因是通过其构造函数管理被装饰的对象,以此来限制具体装饰器的构造方法必须传入被装饰的对象。

  • 具体装饰器(Decoration)

继承抽象装饰器。用于增强对被装饰对象某一功能的特定装饰逻辑

三、案例

核心组件抽象接口

复制代码
public interface Coffee {
    /**
     * 获取描述信息
     */
    String getDescription();

    /**
     * 获取花费
     */
    double getCost();
}

核心组件具体实现

黑咖啡 就是核心

java 复制代码
public class BlackCoffee implements Coffee{
    @Override
    public String getDescription() {
        return "黑咖啡";
    }

    @Override
    public double getCost() {
        return 10;
    }
}

抽象装饰器

java 复制代码
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
    @Override
    public String getDescription() {
        return coffee.getDescription();
    }

    @Override
    public double getCost() {
        return coffee.getCost();
    }
}

具体装饰器

给咖啡加牛奶

java 复制代码
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription()+ " 加奶";
    }

    @Override
    public double getCost() {
        return super.getCost()+ 5 ;
    }

}

给咖啡加糖

java 复制代码
public class SugarDecorator extends CoffeeDecorator{
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", 加糖";
    }

    @Override
    public double getCost() {
        return super.getCost() + 2;
    }
}

测试

在存在多个装饰器具体子类的情况下,可以动态地对现有对象随心所欲进行嵌套包装

上面的例子也可以加2分牛牛奶一份糖,可以随心所欲的进行装饰。

四、装饰器模式在jdk的应用

java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。

继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入流

①组件接口,相当于Component:

InputStream

OutputStream

Reader

Writer

②组件的实现类,相当于ConcreteComponent

FileInputStream

③装饰器接口,相当于Decorator

FilterInputStream

FilterOutputStream

FilterRead

FilterWriter

④装饰器类

BufferedInputStream继承自FilterInputStream

使用说明:我们可以用BufferedInputStream修饰FileInputStream

例如

java 复制代码
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 
//其中file为某个具体文件的File或者FileDescription对象
java 复制代码
FileWriter file = new FileWriter("sample.txt");
BufferedWriter writer = new BufferedWriter(file);
writer.write("a small amount of sample text");
writer.newLine();
writer.close();

五、优缺点

优点

由于装饰器对象和被装饰的对象都实现于核心抽象接口,根据面向接口编程原则,它们具有相同的行为。

装饰器不仅可以将已有对象进行包装,也可以对装饰器对象嵌套包装。

通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。

避免多个被装饰对象与装饰器而导致最终类数量上的膨胀。
缺点

每当为被装饰对象添加新的功能,都需要为其新建一个装饰类

六、适用场景

动态功能扩展: 运行时为对象添加或移除功能(如日志、缓存、加密)
避免多层继承: 替代复杂的继承树(如 BufferedFileReader、EncryptedFileReader)
透明性要求: 客户端无需感知对象是否被装饰(保持接口一致性)。
功能组合复用: 支持多种功能的自由组合(如 压缩 + 加密 文件流)

相关推荐
开发者小天18 小时前
python中For Loop的用法
java·服务器·python
flushmeteor18 小时前
JDK源码-基础类-String
java·开发语言
毕设源码-钟学长18 小时前
【开题答辩全过程】以 基于ssm的空中停车场管理系统为例,包含答辩的问题和答案
java
不愿是过客19 小时前
java实战干货——长方法深递归
java
懵萌长颈鹿19 小时前
装饰器模式 (Decorator Pattern)
装饰器模式
小北方城市网20 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
六义义20 小时前
java基础十二
java·数据结构·算法
毕设源码-钟学长21 小时前
【开题答辩全过程】以 基于SpringBoot的智能书城推荐系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
笨手笨脚の1 天前
深入理解 Java 虚拟机-03 垃圾收集
java·jvm·垃圾回收·标记清除·标记复制·标记整理
莫问前路漫漫1 天前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程