Java设计模式之装饰器模式

装饰器模式是一种结构型设计模式,它允许动态地将责任附加到对象上。装饰器模式是通过创建一个包装对象,也就是装饰器,来包裹真实对象,从而实现对真实对象的功能增强。装饰器模式可以在不修改原有对象的情况下,动态地添加功能。

装饰器模式通常由以下几个组件组成:

1.Component(组件接口):定义了一个对象接口,可以给这些对象动态地添加职责。

2.ConcreteComponent(具体组件):实现了组件接口,是被装饰的对象。

3.Decorator(装饰器抽象类):持有一个指向组件对象的引用,并实现了组件接口。通常是一个抽象类,用于定义装饰器的基本行为。

4.ConcreteDecorator(具体装饰器):扩展了装饰器抽象类,实现了具体的装饰功能。

开始上代码

首先我们定义一个咖啡

java 复制代码
// 组件接口
interface Coffee {
    double cost();
    String getDescription();
}

咖啡分很多种类,我们先来一个浓缩咖啡

java 复制代码
// 具体组件 - 浓缩咖啡
class Espresso implements Coffee {
    @Override
    public double cost() {
        return 1.5;
    }

    @Override
    public String getDescription() {
        return "Espresso";
    }
}

然后我觉得浓缩咖啡有点苦,所以我想加点糖和牛奶

所以这里我们要开始上装饰器了

java 复制代码
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

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

    @Override
    public String getDescription() {
        return coffee.getDescription();
    }
}

加奶的装饰器

java 复制代码
// 具体装饰器 - 加牛奶
class Milk extends CoffeeDecorator {
    public Milk(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.5;
    }

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

加糖的装饰器

java 复制代码
// 具体装饰器 - 加糖
class Sugar extends CoffeeDecorator {
    public Sugar(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.2;
    }

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

然后测试一下

java 复制代码
public class Test {

    public static void main(String[] args) {
        // 点一杯浓缩咖啡
        Coffee espresso = new Espresso();
        System.out.println("Espresso: " + espresso.getDescription() + " - Cost: $" + espresso.cost());

        // 加牛奶
        Coffee espressoWithMilk = new Milk(espresso);
        System.out.println("Espresso with Milk: " + espressoWithMilk.getDescription() + " - Cost: $" + espressoWithMilk.cost());

        // 加糖
        Coffee espressoWithSugar = new Sugar(espresso);
        System.out.println("Espresso with Sugar: " + espressoWithSugar.getDescription() + " - Cost: $" + espressoWithSugar.cost());

        // 加牛奶和糖
        Coffee espressoWithMilkAndSugar = new Sugar(new Milk(espresso));
        System.out.println("Espresso with Milk and Sugar: " + espressoWithMilkAndSugar.getDescription() + " - Cost: $" + espressoWithMilkAndSugar.cost());
    }
}

运行结果

可以发现这个模式很好理解,看起来也比较实用的样子

相关推荐
nice_lcj5208 分钟前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
秋天的怀念_David23 分钟前
算法一千零一夜 · 第二十六夜 协议的母语
java·spring boot·算法
灿飞23 分钟前
Kotlin与Java虚拟机八:控制流与 when:卫语句、上下文相关解析与穷尽性
java·kotlin
文丑颜不良啊1 小时前
LeetCode2021~2040题目解析
java·leetcode
bksczm1 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
liangbo72 小时前
Spring系列03:Bean 的三种注册方式
java·spring
余槐i2 小时前
MySQL 8.0 联合索引走错:为什么加了索引查询反而从 200ms 变成 8s
java·spring boot·mysql·docker·性能优化
SL_staff2 小时前
制造业订单交付总在最后一刻爆雷?用结构化计划模板打通跨系统协同断点
java·开源·全栈
做科研的周师兄2 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
有点小困9772 小时前
Spring Boot 异步任务 ClassLoader 踩坑实录:ClassNotFoundException 的诡异真相
java