编程自学指南:java程序设计开发,Java 装饰模式(Decorator),装饰模式的核心思想:动态扩展对象功能,装饰模式与适配器、代理模式的差异,装饰模式替代继承,避免类爆炸

编程自学指南:java程序设计开发,Java 装饰模式(Decorator)

一、课程信息

学习目标

  1. 理解装饰模式的核心思想:动态扩展对象功能
  2. 掌握四大核心角色的设计方法
  3. 能通过装饰模式替代继承,避免类爆炸
  4. 区分装饰模式与适配器、代理模式的差异

二、课程导入:生活中的装饰

🌰 场景 1:星巴克咖啡

  • 基础咖啡(黑咖啡)→ 加奶 → 加糖浆 → 加奶油
  • 传统继承方式:每加一种配料创建一个子类(拿铁 = 咖啡 + 奶,焦糖拿铁 = 拿铁 + 糖浆),导致类爆炸
  • 装饰模式方案:用装饰器动态包装基础咖啡

三、核心概念与角色

1. 模式定义

动态地给一个对象添加额外的职责,就像给房子装修一样。
核心:通过组合替代继承,实现功能的灵活扩展

2. 四大核心角色

角色名称作用咖啡案例类比
抽象构件定义对象的核心功能接口Beverage(有cost()方法)
具体构件核心功能的具体实现Coffee(黑咖啡)
装饰器抽象类继承 / 实现抽象构件,持有被装饰对象的引用CondimentDecorator(配料基类)
具体装饰器实现额外功能,调用被装饰对象的方法MilkDecoratorSugarDecorator

四、基础实现与案例

🔧 案例 1:星巴克咖啡配料(核心案例)

步骤 1:定义抽象构件
// 饮料抽象类
abstract class Beverage {
    protected String description = "未知饮料";

    public String getDescription() { return description; }
    public abstract double cost();
}
步骤 2:实现具体构件
// 黑咖啡
class Coffee extends Beverage {
    public Coffee() { description = "黑咖啡"; }
    public double cost() { return 10.0; }
}

// 茶
class Tea extends Beverage {
    public Tea() { description = "茶"; }
    public double cost() { return 8.0; }
}
步骤 3:定义装饰器抽象类
// 配料装饰器(继承自Beverage)
abstract class CondimentDecorator extends Beverage {
    protected Beverage beverage; // 持有被装饰的饮料对象

    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}
步骤 4:实现具体装饰器
// 加奶
class MilkDecorator extends CondimentDecorator {
    public MilkDecorator(Beverage beverage) {
        super(beverage);
        description = beverage.getDescription() + ", 加奶";
    }

    public double cost() {
        return beverage.cost() + 2.0; // 奶的价格
    }
}

// 加糖浆
class SugarDecorator extends CondimentDecorator {
    public SugarDecorator(Beverage beverage) {
        super(beverage);
        description = beverage.getDescription() + ", 加糖浆";
    }

    public double cost() {
        return beverage.cost() + 1.5;
    }
}
步骤 5:客户端调用
public class CoffeeShop {
    public static void main(String[] args) {
        // 基础咖啡加奶和糖浆
        Beverage coffee = new Coffee();
        coffee = new MilkDecorator(coffee);
        coffee = new SugarDecorator(coffee);
        
        System.out.println(coffee.getDescription() + ",价格:" + coffee.cost());
        // 输出:黑咖啡, 加奶, 加糖浆,价格:13.5
    }
}

五、进阶案例:手机功能扩展

需求:为手机动态添加拍照、音乐、快充功能

1. 抽象构件:手机核心功能
interface Phone {
    void use(); // 使用手机
}
2. 具体构件:基础手机
class BasicPhone implements Phone {
    public void use() {
        System.out.println("打电话、发短信");
    }
}
3. 装饰器抽象类
abstract class PhoneDecorator implements Phone {
    protected Phone phone;

    public PhoneDecorator(Phone phone) {
        this.phone = phone;
    }
}
4. 具体装饰器
// 拍照功能
class CameraDecorator extends PhoneDecorator {
    public CameraDecorator(Phone phone) {
        super(phone);
    }

    public void use() {
        phone.use(); // 先执行原有功能
        takePhoto(); // 新增拍照功能
    }

    private void takePhoto() {
        System.out.println("拍照:咔嚓!");
    }
}

// 快充功能
class FastChargeDecorator extends PhoneDecorator {
    public FastChargeDecorator(Phone phone) {
        super(phone);
    }

    public void use() {
        phone.use();
        chargeFast();
    }

    private void chargeFast() {
        System.out.println("快充已开启,30分钟充满");
    }
}

六、装饰模式 vs 继承

特性继承装饰模式
扩展方式静态(编译时确定)动态(运行时组合)
类数量多(每个功能组合一个类)少(基础类 + 装饰器)
灵活性低(需修改继承层次)(自由组合装饰器)
代码复用差(子类只能继承父类功能)(装饰器可重复使用)

七、JDK 中的装饰模式

1. InputStream 系列

InputStream is = new FileInputStream("data.txt");
is = new BufferedInputStream(is); // 装饰为缓冲流
is = new DataInputStream(is);      // 装饰为数据输入流

2. StringBuilder 的 append 方法

通过方法调用链动态添加内容,本质是方法级别的装饰

八、适用场景与优缺点

✅ 优点

  1. 动态扩展:无需修改原有代码,随时添加 / 删除功能
  2. 解耦:功能模块独立,可自由组合
  3. 避免类爆炸:替代多层继承

⚠️ 缺点

  • 多层装饰:过度使用会导致代码复杂(如InputStream嵌套过深)
  • 性能损耗:每层装饰增加方法调用开销

🔥 适用场景

  1. 功能动态叠加:如日志功能、缓存功能
  2. 替代继承:避免子类数量爆炸
  3. Java IO/NIO:典型的装饰模式应用

九、课堂练习

练习 1:扩展咖啡案例

需求:新增 "奶油" 配料,价格 3 元,修改描述为 "加奶油"

练习 2:文本处理装饰器

需求

  • 基础功能:输出文本
  • 装饰器 1:添加前后缀(如 <<文本>>)
  • 装饰器 2:转为大写

十、课程总结

知识图谱:

装饰模式  
   ↳ 核心:组合替代继承,动态扩展功能  
   ↳ 角色:抽象构件→具体构件→装饰器抽象→具体装饰器  
   ↳ 优势:灵活扩展、避免类爆炸  
   ↳ 与继承区别:动态vs静态,组合vs父子  

口诀记忆:

“装饰模式像装修,功能动态往上加,
继承层次太复杂,组合装饰来救场,
构件装饰分清楚,层层包装功能强!”

十一、课后作业

必做 1:实现日志装饰器

需求

  • 基础功能:执行数据库操作
  • 装饰器 1:记录操作开始 / 结束时间
  • 装饰器 2:记录操作参数

必做 2:分析 Java IO 装饰器链

任务

  1. 写出BufferedReader的装饰器链(从FileReader开始)
  2. 说明每个装饰器的作用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zl515035644

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值