装饰器模式
装饰器模式属于结构型设计模式。它允许向一个现有的对象添加新的功能,同时又不改变其结构。
例如:给一个普通的杯子加上杯盖、杯套,让它具有保温防烫等功能,而杯子本身的基本结构并没有发生变化。在软件开发过程中,当我们需要在运行时动态的为对象添加职责,并且避免通过继承来扩展功能带来的类层次结构复杂问题时,装饰器模式就派上用场了。
装饰器模式主要包含以下几个角色:
1.抽象组件(component):定义一个抽象接口,规范具体组件和装饰器的行为
2.具体组件(concrete component):实现抽象组件接口,是被装饰的具体对象
3.抽象装饰器(decorator):继承或实现抽象组件接口,持有一个抽象组件的引用,并定义一个可以动态添加职责的方法
4.具体装饰器(concrete decorator):实现抽象装饰器接口,负责为具体组件添加具体功能
核心思想
1.动态扩展:在运行时添加/删除功能,而非编译时
2.组合优于继承:通过对象组合实现功能叠加,避免类爆炸
3.透明性:装饰后的对象与原对象接口一致,对客户端透明
典型使用场景
1.I/O流操作(Java原生)如InputStream、BufferedInputStream、DataInputStream等,都是典型的装饰器模式应用
2.权限控制/日志记录等通用功能增强,在不改变核心业务逻辑的前提下,为服务添加日志、缓存、安全等功能。
3.UI组件扩展,比如按钮组件加上边框、阴影、滚动等效果
4.Spring的AOP(面向切面编程)Spring使用了类似装饰器的思想来实现方法拦截和增强。
装饰器模式实现步骤
1.故事背景:机器人功能扩展的两种方案
在智能家居领域,某科技公司推出了第一代家用机器人,它具备三个核心功能:对话、唱歌和播放音乐。
// 第一代机器人:基础功能 interface Robot {void talk(); // 对话void sing(); // 唱歌void playMusic(); // 播放音乐 }class FirstGenerationRobot implements Robot {@Overridepublic void talk() {System.out.println("机器人:你好,我能陪你聊天");}@Overridepublic void sing() {System.out.println("机器人:正在播放《青花瓷》");}@Overridepublic void playMusic() {System.out.println("机器人:正在播放轻音乐");} }
随着用户需求升级,厂家希望扩展机器人的功能,让它能够扫地和跳舞。针对这个需求,有两种技术方案可供选择:
⑴.方案一:传统继承(厂家升级方案)
厂家选择开发第二代机器人,通过继承第一代产品并添加新功能:
// 基础接口:第一代机器人支持的功能 interface Robot {void talk();void sing();void playMusic(); }
// 第一代机器人(基础实现) class FirstGenerationRobot implements Robot {@Overridepublic void talk() {System.out.println("对话中...");}@Overridepublic void sing() {System.out.println("正在唱歌...");}@Overridepublic void playMusic() {System.out.println("播放音乐中...");} }// 第二代机器人:通过继承方式扩展功能 class SecondGenerationRobot extends FirstGenerationRobot {public void sweep() {System.out.println("正在扫地...");}public void dance() {System.out.println("正在跳舞...");} }
测试代码
public class InheritanceTest {public static void main(String[] args) {System.out.println("=== 继承方式测试 ===");SecondGenerationRobot robot = new SecondGenerationRobot();robot.talk();robot.sing();robot.playMusic();robot.sweep(); // 扩展功能robot.dance(); // 扩展功能 } }
⑵.方案二:装饰器模式