rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 装饰模式(Decorator Pattern)

  • 一、装饰模式核心概念(通用)
    • 1. 定义
    • 2. 意图
    • 3. 通用核心组件
  • 二、装饰模式详细解析(以 “咖啡加调料” 为例)
    • 1. 结构
    • 2. 类图(Mermaid)
    • 3. 时序图(Mermaid)
    • 4. 优点
    • 5. 缺点
  • 三、Java 代码实现(咖啡加调料示例)
    • 1. 抽象构件(Coffee)
    • 2. 具体构件(Espresso)
    • 3. 抽象装饰器(CoffeeDecorator)
    • 4. 具体装饰器(MilkDecorator、SugarDecorator)
    • 5. 客户端(Client)
    • 6. 输出结果
  • 四、适用环境
  • 五、模式分析
    • 1. 核心本质
    • 2. 与其他模式的区别
    • 3. 关键设计原则
  • 六、模式扩展
    • 1. 透明装饰模式(Transparent Decorator)
    • 2. 半透明装饰模式(Semi-Transparent Decorator)
    • 3. 可撤销装饰模式(Undoable Decorator)
  • 七、模式应用(通用 + Android)
    • 1. 通用领域应用
    • 2. Android 中的应用
      • (1)ContextWrapper 与 Context 的装饰(核心应用)
      • (2)RecyclerView.ItemDecoration(UI 装饰)
      • (3)Window.DecorView(窗口装饰)
  • 八、总结
  • JDK

装饰模式(Decorator Pattern)

Java中的 IO流

装饰模式是结构型设计模式的核心成员,其核心目标是动态地给一个对象添加一些额外的职责,且无需修改原对象的结构。它如同日常生活中 “给手机贴保护膜、装手机壳”—— 手机(原对象)的核心功能(通话、上网)不变,但通过保护膜(装饰)增加 “防刮” 功能,通过手机壳(装饰)增加 “防摔” 功能,且装饰可灵活组合(贴了膜也能装壳)。

一、装饰模式核心概念(通用)

1. 定义

动态地给一个对象添加一些额外的职责。就扩展功能而言,装饰模式比继承更灵活 —— 它通过 “组合” 而非 “继承” 实现功能扩展,避免了继承导致的类爆炸问题。

2. 意图

  • 动态扩展功能:无需修改原对象代码,即可为对象新增功能(符合 “开闭原则”)。
  • 避免多重继承:若用继承扩展多个功能,会产生 “功能组合爆炸”(如 “咖啡 + 牛奶 + 糖” 需创建MilkSugarCoffee类),装饰模式通过组合实现灵活扩展。
  • 功能可组合 / 撤销:多个装饰器可嵌套使用(如 “牛奶装饰 + 糖装饰”),若设计支持,还可撤销装饰(如移除糖的功能)。

3. 通用核心组件

装饰模式的核心是通过 “抽象装饰器” 持有 “抽象构件” 引用,实现功能的嵌套扩展,包含 4 个核心角色:

角色名称职责描述
Component(抽象构件)定义被装饰对象和装饰器的共同接口(或抽象类),声明核心业务方法(如咖啡的 “计算价格”“获取描述”)。
ConcreteComponent(具体构件)实现抽象构件,是 “被装饰的原始对象”(如基础咖啡Espresso),提供核心业务逻辑的默认实现。
Decorator(抽象装饰器)抽象类,实现抽象构件接口,持有一个 Component 类型的引用(指向被装饰的对象)。它的核心作用是 “传递业务方法调用”—— 在调用被装饰对象的方法前后,可添加额外逻辑(装饰功能)。
ConcreteDecorator(具体装饰器)继承抽象装饰器,实现具体的装饰功能(如 “加牛奶”MilkDecorator、“加糖”SugarDecorator)。在重写的业务方法中,先调用被装饰对象的方法,再添加自身的装饰逻辑(如增加价格、补充描述)。

二、装饰模式详细解析(以 “咖啡加调料” 为例)

以 “咖啡订单系统” 为场景:基础咖啡(如Espresso、Latte)可添加多种调料(牛奶、糖、巧克力),每种调料需额外收费且需在订单描述中体现。若用继承实现,“Espresso + 牛奶 + 糖” 需创建MilkSugarEspresso类,功能组合越多,类数量爆炸;装饰模式通过 “基础咖啡 + 调料装饰器” 的组合,灵活实现任意调料搭配。

1. 结构

  1. Component(抽象构件):Coffee,定义cost()(计算价格)和getDescription()(获取订单描述)方法。
  2. ConcreteComponent(具体构件):Espresso(浓缩咖啡),实现cost()(基础价 20 元)和getDescription()(“浓缩咖啡”)。
  3. Decorator(抽象装饰器):CoffeeDecorator,继承Coffee,持有Coffee引用,重写cost()和getDescription(),默认调用被装饰对象的方法(传递调用)。
  4. ConcreteDecorator(具体装饰器):MilkDecorator(加牛奶,+5 元)、SugarDecorator(加糖,+3 元),重写方法时添加自身的价格和描述。

2. 类图(Mermaid)

classDiagram
    %% 抽象构件:咖啡接口
    class Coffee {
        <<Abstract>>
        +cost(): double  // 计算价格
        +getDescription(): String  // 获取订单描述
    }

    %% 具体构件:浓缩咖啡(被装饰的原始对象)
    class Espresso {
        +Espresso()
        +cost(): double  // 基础价20元
        +getDescription(): String  // 描述:浓缩咖啡
    }

    %% 抽象装饰器:咖啡装饰器(持有Coffee引用)
    class CoffeeDecorator {
        <<Abstract>>
        -coffee: Coffee  // 持有被装饰的Coffee对象
        +CoffeeDecorator(coffee: Coffee)
        +cost(): double  // 传递调用,可扩展
        +getDescription(): String  // 传递调用,可扩展
    }

    %% 具体装饰器1:加牛奶(+5元)
    class MilkDecorator {
        +MilkDecorator(coffee: Coffee)
        +cost(): double  // 被装饰对象价格 +5
        +getDescription(): String  // 被装饰对象描述 + ",加牛奶"
    }

    %% 具体装饰器2:加糖(+3元)
    class SugarDecorator {
        +SugarDecorator(coffee: Coffee)
        +cost(): double  // 被装饰对象价格 +3
        +getDescription(): String  // 被装饰对象描述 + ",加糖"
    }

    %% 关系梳理
    %% 具体构件实现抽象构件
    Coffee <|-- Espresso
    %% 抽象装饰器实现抽象构件(保证接口一致)
    Coffee <|-- CoffeeDecorator
    
    %% 具体装饰器继承抽象装饰器
    CoffeeDecorator <|-- MilkDecorator
    
    %% 具体装饰器继承抽象装饰器
    CoffeeDecorator <|-- SugarDecorator
    CoffeeDecorator o-- Coffee : 持有(核心:装饰器关联被装饰对象)

3. 时序图(Mermaid)

以 “客户端点一杯‘浓缩咖啡 + 牛奶 + 糖’” 为例,展示装饰模式的调用流程(嵌套装饰的方法调用链):

sequenceDiagram
    participant Client(客户端)
    participant Espresso(具体构件:浓缩咖啡)
    participant MilkDecorator(具体装饰器:加牛奶)
    participant SugarDecorator(具体装饰器:加糖)

    %% 1. 客户端创建基础咖啡(被装饰对象)
    Client->>Espresso: new Espresso()
    Espresso-->>Client: 返回Espresso实例

    %% 2. 用牛奶装饰器包装基础咖啡
    Client->>MilkDecorator: new MilkDecorator(Espresso)
    MilkDecorator-->>Client: 返回包装后的MilkDecorator实例

    %% 3. 用糖装饰器包装“牛奶咖啡”(嵌套装饰)
    Client->>SugarDecorator: new SugarDecorator(MilkDecorator)
    SugarDecorator-->>Client: 返回包装后的SugarDecorator实例

    %% 4. 客户端调用最终装饰对象的cost()(计算总价格)
    Client->>SugarDecorator: cost()
    %% 4.1 糖装饰器调用牛奶装饰器的cost()
    SugarDecorator->>MilkDecorator: cost()
    %% 4.2 牛奶装饰器调用基础咖啡的cost()
    MilkDecorator->>Espresso: cost()
    %% 4.3 基础咖啡返回基础价格
    Espresso-->>MilkDecorator: 20.0(基础价)
    %% 4.4 牛奶装饰器加5元,返回25元
    MilkDecorator-->>SugarDecorator: 25.0(20+5)
    %% 4.5 糖装饰器加3元,返回28元
    SugarDecorator-->>Client: 28.0(25+3)

    %% 5. 客户端调用getDescription()(获取总描述)
    Client->>SugarDecorator: getDescription()
    SugarDecorator->>MilkDecorator: getDescription()
    MilkDecorator->>Espresso: getDescription()
    Espresso-->>MilkDecorator: "浓缩咖啡"
    MilkDecorator-->>SugarDecorator: "浓缩咖啡,加牛奶"
    SugarDecorator-->>Client: "浓缩咖啡,加牛奶,加糖"

4. 优点

  • 动态灵活扩展:无需修改原对象代码,可在运行时为对象添加 / 移除功能(如给咖啡加 / 减牛奶),符合 “开闭原则”。
  • 避免类爆炸:若用继承实现 “咖啡 + N 种调料”,需2^N个类;装饰模式只需 “基础咖啡类 + N 个调料装饰器类”,类数量线性增长。
  • 功能可组合:多个装饰器可嵌套使用(如 “牛奶 + 糖 + 巧克力”),实现任意功能组合。
  • 符合合成复用原则:通过 “组合” 而非 “继承” 扩展功能,降低类间耦合(装饰器与被装饰对象通过接口关联)。

5. 缺点

  • 增加系统复杂度:每新增一个功能需创建一个装饰器类,可能导致类数量增多(但比继承少);嵌套装饰会增加调试难度(需跟踪多层调用链)。
  • 客户端需了解装饰器逻辑:客户端需知道如何组合装饰器(如 “先加牛奶再加糖”),若装饰器顺序影响结果(如 “先加冰再加糖” 和 “先加糖再加冰”),需客户端控制顺序。
  • 不能替代继承的全部场景:若功能需修改原对象的核心逻辑(而非新增),装饰模式不适用(需用其他模式如策略模式)。

三、Java 代码实现(咖啡加调料示例)

1. 抽象构件(Coffee)

定义被装饰对象和装饰器的共同接口:

// 抽象构件:咖啡接口
public abstract class Coffee {
    // 计算价格
    public abstract double cost();
    // 获取订单描述
    public abstract String getDescription();
}

2. 具体构件(Espresso)

被装饰的原始对象,提供基础功能实现:

// 具体构件:浓缩咖啡(基础咖啡)
public class Espresso extends Coffee {
    // 基础价格:20元
    @Override
    public double cost() {
        return 20.0;
    }

    // 基础描述
    @Override
    public String getDescription() {
        return "浓缩咖啡";
    }
}

// (可选)其他具体构件:拿铁咖啡(基础价25元)
class Latte extends Coffee {
    @Override
    public double cost() {
        return 25.0;
    }

    @Override
    public String getDescription() {
        return "拿铁咖啡";
    }
}

3. 抽象装饰器(CoffeeDecorator)

持有 Coffee 引用,传递方法调用,为具体装饰器提供基础:

// 抽象装饰器:咖啡装饰器
public abstract class CoffeeDecorator extends Coffee {
    // 持有被装饰的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();
    }
}

4. 具体装饰器(MilkDecorator、SugarDecorator)

实现具体装饰功能,扩展原对象的方法:

// 具体装饰器1:加牛奶(+5元)
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    // 重写cost():基础价格 + 牛奶价格
    @Override
    public double cost() {
        return coffee.cost() + 5.0;
    }

    // 重写getDescription():基础描述 + 牛奶描述
    @Override
    public String getDescription() {
        return coffee.getDescription() + ",加牛奶";
    }
}

// 具体装饰器2:加糖(+3元)
public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

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

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

// (可选)具体装饰器3:加巧克力(+8元)
class ChocolateDecorator extends CoffeeDecorator {
    public ChocolateDecorator(Coffee coffee) {
        super(coffee);
    }

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

    @Override
    public String getDescription() {
        return coffee.getDescription() + ",加巧克力";
    }
}

5. 客户端(Client)

通过组合装饰器,动态为基础咖啡添加功能:

// 客户端:点咖啡(组合装饰器)
public class Client {
    public static void main(String[] args) {
        // 场景1:基础浓缩咖啡(无装饰)
        Coffee espresso = new Espresso();
        System.out.println("订单1:" + espresso.getDescription() + ",总价:" + espresso.cost() + "元");

        // 场景2:浓缩咖啡 + 牛奶
        Coffee milkEspresso = new MilkDecorator(espresso);
        System.out.println("订单2:" + milkEspresso.getDescription() + ",总价:" + milkEspresso.cost() + "元");

        // 场景3:浓缩咖啡 + 牛奶 + 糖(嵌套装饰)
        Coffee milkSugarEspresso = new SugarDecorator(milkEspresso);
        System.out.println("订单3:" + milkSugarEspresso.getDescription() + ",总价:" + milkSugarEspresso.cost() + "元");

        // 场景4:拿铁咖啡 + 巧克力 + 糖(换基础咖啡,组合其他装饰器)
        Coffee latte = new Latte();
        Coffee chocolateSugarLatte = new SugarDecorator(new ChocolateDecorator(latte));
        System.out.println("订单4:" + chocolateSugarLatte.getDescription() + ",总价:" + chocolateSugarLatte.cost() + "元");
    }
}

6. 输出结果

订单1:浓缩咖啡,总价:20.0元
订单2:浓缩咖啡,加牛奶,总价:25.0元
订单3:浓缩咖啡,加牛奶,加糖,总价:28.0元
订单4:拿铁咖啡,加巧克力,加糖,总价:36.0元

四、适用环境

装饰模式适用于以下场景,核心判断标准是 “需动态扩展功能,且避免用继承”:

  1. 动态扩展单个对象的功能:需为对象新增功能,且不影响其他同类对象(如给某杯咖啡加牛奶,不影响其他咖啡)。
  2. 避免多重继承导致的类爆炸:若用继承实现多个功能组合(如 “咖啡 + 牛奶 + 糖”),会产生大量组合类,装饰模式通过组合解决。
  3. 功能可组合 / 撤销:需灵活组合多个功能(如 “牛奶 + 糖 + 巧克力”),或需在运行时撤销功能(如给咖啡去掉糖)。
  4. 不能修改原对象代码:原对象属于第三方库或已稳定运行,不允许修改其源代码,需通过外部装饰扩展功能。

五、模式分析

1. 核心本质

装饰模式的本质是 “接口一致 + 组合嵌套 + 动态扩展”:

  • 接口一致:装饰器与被装饰对象实现相同接口(Coffee),确保客户端可透明使用(无需区分 “基础咖啡” 和 “装饰后的咖啡”)。
  • 组合嵌套:装饰器通过持有Coffee引用,实现 “装饰器包装装饰器” 的嵌套结构(如SugarDecorator(MilkDecorator(Espresso))),方法调用链自动传递。
  • 动态扩展:通过新增装饰器类(如ChocolateDecorator)扩展功能,无需修改原代码,符合 “开闭原则”。

2. 与其他模式的区别

模式核心差异典型场景
装饰模式不改变接口,动态新增功能,组合嵌套咖啡加调料、IO 流缓冲
适配器模式改变接口(适配不兼容接口),不新增功能旧系统接口适配新系统
桥接模式分离抽象与实现,解决多维度变化,不新增功能形状 + 颜色、遥控器 + 电视
继承静态扩展功能,子类与父类强耦合功能固定,无需动态扩展

3. 关键设计原则

  • 接口一致性:装饰器必须实现与被装饰对象相同的接口(Coffee),确保客户端可透明使用(“里氏替换原则” 的体现)。
  • 装饰器轻量:具体装饰器应只负责单一功能(“单一职责原则”),如MilkDecorator只处理 “加牛奶”,避免一个装饰器实现多个功能。
  • 传递调用不可断:抽象装饰器的cost()和getDescription()必须调用被装饰对象的对应方法(coffee.cost()),否则会中断调用链,导致基础功能丢失。

六、模式扩展

装饰模式可根据场景需求扩展出以下变体:

1. 透明装饰模式(Transparent Decorator)

  • 特点:客户端完全不知道装饰器的存在,只通过抽象构件(Coffee)接口操作对象(如客户端只调用Coffee的cost(),不关心是Espresso还是MilkDecorator)。
  • 优点:客户端代码简洁,符合 “依赖倒置原则”(依赖抽象而非具体)。
  • 缺点:若装饰器需新增额外方法(如MilkDecorator的getMilkAmount()),客户端无法调用(需强制转型,破坏透明性)。

2. 半透明装饰模式(Semi-Transparent Decorator)

  • 特点:客户端知道具体装饰器的存在,可调用装饰器的额外方法(如MilkDecorator的setMilkAmount(100))。
  • 实现:具体装饰器新增额外方法,客户端需将对象转型为具体装饰器类型才能调用。
  • 优点:支持装饰器的额外功能调用。
  • 缺点:破坏了接口透明性,客户端需依赖具体装饰器类,耦合度提高。
// 半透明装饰模式示例:MilkDecorator新增额外方法
class MilkDecorator extends CoffeeDecorator {
    private int milkAmount; // 牛奶量(ml)

    public MilkDecorator(Coffee coffee) {
        super(coffee);
        this.milkAmount = 50; // 默认50ml
    }

    // 额外方法:设置牛奶量
    public void setMilkAmount(int amount) {
        this.milkAmount = amount;
    }

    // 重写cost():牛奶量越多,价格越高
    @Override
    public double cost() {
        return coffee.cost() + (milkAmount / 10.0); // 每10ml加1元
    }

    @Override
    public String getDescription() {
        return coffee.getDescription() + ",加" + milkAmount + "ml牛奶";
    }
}

// 客户端调用额外方法(需转型)
Coffee milkEspresso = new MilkDecorator(new Espresso());
((MilkDecorator) milkEspresso).setMilkAmount(100); // 强制转型
System.out.println(milkEspresso.getDescription()); // 输出:浓缩咖啡,加100ml牛奶
System.out.println(milkEspresso.cost()); // 输出:20 + 10 = 30.0元

3. 可撤销装饰模式(Undoable Decorator)

  • 特点:装饰器记录被装饰对象的原始状态,支持撤销装饰(移除新增的功能)。
  • 实现:抽象装饰器新增undo()方法,具体装饰器重写undo(),恢复被装饰对象的原始状态。
// 可撤销装饰模式示例
abstract class UndoableCoffeeDecorator extends CoffeeDecorator {
    protected double originalCost; // 记录原始价格
    protected String originalDesc; // 记录原始描述

    public UndoableCoffeeDecorator(Coffee coffee) {
        super(coffee);
        this.originalCost = coffee.cost(); // 保存原始价格
        this.originalDesc = coffee.getDescription(); // 保存原始描述
    }

    // 抽象撤销方法
    public abstract void undo();
}

// 可撤销的牛奶装饰器
class UndoableMilkDecorator extends UndoableCoffeeDecorator {
    public UndoableMilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return originalCost + 5.0;
    }

    @Override
    public String getDescription() {
        return originalDesc + ",加牛奶";
    }

    // 撤销装饰:恢复原始价格和描述(需通过成员变量记录)
    @Override
    public void undo() {
        // 注:实际需设计状态保存机制,此处简化为打印撤销信息
        System.out.println("撤销加牛奶,恢复为:" + originalDesc + ",价格:" + originalCost + "元");
    }
}

// 客户端调用撤销
UndoableCoffeeDecorator milkEspresso = new UndoableMilkDecorator(new Espresso());
System.out.println("装饰后:" + milkEspresso.getDescription() + ",价格:" + milkEspresso.cost());
milkEspresso.undo(); // 输出:撤销加牛奶,恢复为:浓缩咖啡,价格:20.0元

七、模式应用(通用 + Android)

1. 通用领域应用

  • Java IO 流:装饰模式的经典应用!InputStream/OutputStream是抽象构件,FileInputStream/FileOutputStream是具体构件,BufferedInputStream/DataInputStream是具体装饰器(如BufferedInputStream为 FileInputStream添加 “缓冲” 功能)。

    // Java IO流的装饰模式示例
    InputStream in = new FileInputStream("test.txt"); // 具体构件
    InputStream bufferedIn = new BufferedInputStream(in); // 装饰:加缓冲
    InputStream dataIn = new DataInputStream(bufferedIn); // 嵌套装饰:加数据读取功能
    
  • GUI 组件框架:如 Swing 中,JComponent是抽象构件,JButton是具体构件,BorderDecorator(加边框)、ColorDecorator(加颜色)是装饰器,动态为按钮添加外观功能。

  • 日志框架:如 Log4j 中,Appender是抽象构件,ConsoleAppender是具体构件,RollingFileAppender(滚动日志)、AsyncAppender(异步日志)是装饰器,扩展日志输出功能。

2. Android 中的应用

Android 框架大量使用装饰模式实现 “动态扩展组件功能”,核心场景集中在Context包装、UI 装饰和资源处理:

(1)ContextWrapper 与 Context 的装饰(核心应用)

  • 角色对应:
    • Context:抽象构件(定义 Android 应用的核心上下文接口,如startActivity()、getSharedPreferences());
    • ContextImpl:具体构件(Context的实际实现类,封装底层系统调用);
    • ContextWrapper:抽象装饰器(继承Context,持有Context引用,传递方法调用);
    • Activity/Service/Application:具体装饰器(继承ContextWrapper,扩展Context功能,如Activity新增setContentView(),Service新增startForeground())。
  • 核心逻辑:Android 中所有Context实例都是 “ContextImpl被ContextWrapper装饰” 的结果。例如,Activity的Context本质是:Activity(装饰器)→ ContextWrapper(抽象装饰器)→ ContextImpl(具体构件),Activity通过装饰扩展了Context的 UI 相关功能。
// Android源码简化逻辑(ContextWrapper)
public class ContextWrapper extends Context {
    Context mBase; // 持有被装饰的Context(实际是ContextImpl)

    public ContextWrapper(Context base) {
        mBase = base;
    }

    // 传递调用:调用mBase的方法
    @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }

    // 其他方法均为传递调用...
}

// Activity作为具体装饰器,扩展Context功能
public class Activity extends ContextWrapper {
    // 新增UI相关功能(装饰逻辑)
    public void setContentView(int layoutResID) {
        // 扩展:加载布局,初始化UI
        getWindow().setContentView(layoutResID);
    }

    // 重写startActivity,添加Activity栈管理逻辑(装饰扩展)
    @Override
    public void startActivity(Intent intent) {
        super.startActivity(intent); // 调用被装饰对象的方法
        // 新增:记录Activity启动栈
        ActivityTaskManager.getInstance().addActivityToStack(this);
    }
}

(2)RecyclerView.ItemDecoration(UI 装饰)

  • 角色对应:
    • RecyclerView的ViewHolder:抽象构件(展示 Item 的核心组件);
    • 自定义ViewHolder:具体构件(实现 Item 的基础 UI);
    • ItemDecoration:抽象装饰器(定义 Item 装饰接口,如onDraw()绘制分割线、getItemOffsets()设置偏移);
    • DividerItemDecoration(系统提供):具体装饰器(实现 “绘制 Item 分割线” 的装饰功能)。
  • 核心逻辑:通过recyclerView.addItemDecoration(decoration)为ViewHolder动态添加装饰(如分割线、Item 间距),无需修改ViewHolder的代码,符合 “开闭原则”。
// Android中使用ItemDecoration装饰RecyclerView Item
RecyclerView recyclerView = findViewById(R.id.recycler_view);
// 添加分割线装饰(具体装饰器)
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapter); // adapter提供具体构件(ViewHolder)

(3)Window.DecorView(窗口装饰)

  • 角色对应:
    • View:抽象构件(UI 组件的基类);
    • ContentView(用户布局):具体构件(用户通过setContentView()设置的布局);
    • DecorView:具体装饰器(继承FrameLayout,持有ContentView,为其添加系统装饰,如标题栏、状态栏、导航栏)。
  • 核心逻辑:Android 窗口的DecorView是 “用户布局的装饰器”—— 用户布局(ContentView)是核心内容,DecorView为其包装系统级 UI(如标题栏),动态扩展窗口功能。

八、总结

装饰模式是 “动态扩展功能” 的核心解决方案,其核心价值在于 “灵活、无侵入、可组合”:

  1. 核心优势:无需修改原代码即可动态扩展功能,避免继承导致的类爆炸,支持功能的灵活组合与撤销,符合 “开闭原则” 和 “合成复用原则”。
  2. 适用场景:需动态扩展单个对象功能、避免多重继承、不能修改原对象代码的场景(如 Java IO 流、Android Context 包装)。
  3. 实践建议:
    • 确保装饰器与被装饰对象实现相同接口(保证透明性);
    • 具体装饰器遵循 “单一职责原则”,每个装饰器只实现一个功能;
    • 避免过度嵌套装饰(如超过 3 层),否则会增加调试难度和性能开销;
    • 若需调用装饰器的额外功能,可使用半透明装饰模式,但需平衡透明性与功能需求。

装饰模式不仅是一种设计技巧,更是一种 “无侵入扩展” 的思维 —— 在不破坏原有系统的前提下,通过外部组合为对象新增能力,是维护大型系统稳定性和灵活性的重要工具

JDK

  • java.io.BufferedInputStream(InputStream)
  • java.io.DataInputStream(InputStream)
  • java.io.BufferedOutputStream(OutputStream)
  • java.util.zip.ZipOutputStream(OutputStream)
  • java.util.Collections#checkedList|Map|Set|SortedSet|SortedMap

最近更新:: 2025/10/22 15:36
Contributors: 罗凯文, luokaiwen