Skip to content

装饰器

更新: 6/22/2025 字数: 0 字 时长: 0 分钟

定义

装饰器模式 (Decorator Pattern) 动态地给对象添加额外职责,提供比继承更灵活的扩展方案。装饰器通过包装对象实现功能增强,同时保持接口兼容性。

角色

  • 组件接口 (Component):定义被装饰对象的接口
  • 具体组件 (Concrete Component):实现组件接口的基础对象
  • 装饰器基类 (Decorator):实现组件接口,维护组件引用
  • 具体装饰器 (Concrete Decorator):添加具体功能的装饰器实现

实现

咖啡订单系统示例

java
// 组件接口
public interface Coffee {
    double cost();
    String description();
}

// 具体组件
public class SimpleCoffee implements Coffee {
    @Override
    public double cost() {
        return 10.0;
    }
    
    @Override
    public String description() {
        return "咖啡";
    }
}

// 装饰器基类
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    
    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }
    
    @Override
    public String description() {
        return decoratedCoffee.description();
    }
}

// 具体装饰器:牛奶
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return super.cost() + 2.0;
    }
    
    @Override
    public String description() {
        return super.description() + ", 牛奶";
    }
}

// 具体装饰器:糖浆
public class SyrupDecorator extends CoffeeDecorator {
    public SyrupDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return super.cost() + 1.5;
    }
    
    @Override
    public String description() {
        return super.description() + ", 糖浆";
    }
}

// 使用示例
public class CoffeeShop {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        coffee = new MilkDecorator(coffee);
        coffee = new SyrupDecorator(coffee);
        
        System.out.println(coffee.description() + " 价格:¥" + coffee.cost());
        // 输出:咖啡,牛奶,糖浆 价格:¥13.5
    }
}

I/O 流装饰器示例

java
// 模拟 InputStream 装饰器
public class LowerCaseInputStream extends FilterInputStream {
    public LowerCaseInputStream(InputStream in) {
        super(in);
    }
    
    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1) ? c : Character.toLowerCase(c);
    }
    
    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result = super.read(b, off, len);
        for (int i = off; i < off + result; i++) {
            b[i] = (byte)Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}

// 使用示例
public class DecoratorDemo {
    public static void main(String[] args) {
        String text = "HELLO DECORATOR PATTERN!";
        try (InputStream in = new LowerCaseInputStream(
                new ByteArrayInputStream(text.getBytes()))) {
            
            int c;
            while ((c = in.read()) != -1) {
                System.out.print((char)c);
            }
            // 输出:hello decorator pattern!
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

优缺点

优点:

  1. 比继承更灵活(运行时添加/移除功能)
  2. 避免子类膨胀问题
  3. 符合开闭原则(扩展开放,修改关闭)
  4. 可组合多个装饰器实现复杂功能

缺点:

  1. 产生大量小对象增加系统复杂度
  2. 多层装饰增加调试难度
  3. 设计不当可能导致装饰链过长
  4. 初始化配置可能变得复杂

应用场景

  1. 动态透明地添加功能
  2. 撤销功能(通过移除装饰层)
  3. 扩展类功能但无法使用继承
  4. I/O 流处理(Java I/O 核心模式)
  5. GUI 组件增强

与其他模式的关系

  • 与适配器模式:适配器改变接口,装饰器增强功能
  • 与代理模式:代理控制访问,装饰器添加功能
  • 与组合模式:装饰器可视为只有一个组件的组合
  • 与策略模式:策略改变行为核心,装饰器添加外围功能

JDK 中的装饰器模式

  1. Java I/O 流体系(FilterInputStream/FilterOutputStream
  2. Java 集合框架的装饰方法(Collections.unmodifiableCollection()
  3. Servlet API 中的HttpServletRequestWrapper
  4. JavaBeans 的PropertyChangeSupport

注意事项

  1. 保持组件接口简洁(避免装饰器实现不必要的方法)
  2. 控制装饰层数(避免过度复杂)
  3. 考虑装饰器顺序(功能叠加可能有顺序依赖)
  4. 注意性能影响(多层包装增加调用开销)
  5. 提供适当的工厂方法简化装饰过程

贡献者

The avatar of contributor named as LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史