设计模式之装饰器模式(I/O流‘、web开发、security案例)

Decorator 是一种结构型设计模式,它动态地给对象添加额外的职责,相比继承更加灵活。装饰器模式通过创建包装对象来实现功能的扩展。

核心思想
  • 运行时扩展:在不修改原有类的情况下动态添加功能

  • 组合优于继承:通过对象组合而非继承实现功能扩展

  • 透明性:装饰后的对象与原对象具有相同的接口

主要角色
  1. Component(抽象组件):定义对象的接口

  2. ConcreteComponent(具体组件):实现基本功能

  3. Decorator(抽象装饰器):继承/实现Component,并持有Component引用

  4. ConcreteDecorator(具体装饰器):实现具体的装饰功能


经典案例:咖啡加料系统

1. 基础实现

// 2. 具体组件
class SimpleCoffee implements Coffee {
    @Override
    public double getCost() {
        return 1.0;
    }
    
    @Override
    public String getDescription() {
        return "普通咖啡";
    }
}

// 3. 抽象装饰器
abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    
    @Override
    public double getCost() {
        return decoratedCoffee.getCost();
    }
    
    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}
// 1. 抽象组件
interface Coffee {
    double getCost();
    String getDescription();
}
// 4. 具体装饰器
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double getCost() {
        return super.getCost() + 0.5;
    }
    
    @Override
    public String getDescription() {
        return super.getDescription() + ",加牛奶";
    }
}

class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double getCost() {
        return super.getCost() + 0.2;
    }
    
    @Override
    public String getDescription() {
        return super.getDescription() + ",加糖";
    }
}
// 客户端
public class DecoratorDemo {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.getDescription() + " ¥" + coffee.getCost());
        
        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.getDescription() + " ¥" + coffee.getCost());
        
        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.getDescription() + " ¥" + coffee.getCost());
    }
}
输出结果:


2. 简化实现(Java I/O风格)

Java I/O 流是装饰器模式的经典应用:

// 模拟InputStream
abstract class InputStream {
    public abstract int read();
}

class FileInputStream extends InputStream {
    @Override
    public int read() {
        System.out.println("读取文件字节");
        return 0;
    }
}

// 装饰器基类
class FilterInputStream extends InputStream {
    protected InputStream in;
    
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
    
    @Override
    public int read() {
        return in.read();
    }
}
// 具体装饰器
class BufferedInputStream extends FilterInputStream {
    public BufferedInputStream(InputStream in) {
        super(in);
    }
    
    @Override
    public int read() {
        System.out.println("缓冲读取");
        return super.read();
    }
}

class DataInputStream extends FilterInputStream {
    public DataInputStream(InputStream in) {
        super(in);
    }
    
    @Override
    public int read() {
        System.out.println("按数据类型读取");
        return super.read();
    }
}

// 客户端
public class IoStyleDemo {
    public static void main(String[] args) {
        InputStream in = new FileInputStream();
        in = new BufferedInputStream(in);
        in = new DataInputStream(in);
        
        in.read();  // 组合功能
    }
}
输出结果:


装饰器模式 vs 继承

特性装饰器模式继承
扩展方式动态组合静态编译时确定
功能组合灵活的多层组合单一继承链
类数量大量小装饰器类需要创建多个子类
运行时影响可以动态添加/移除功能编译时固定

实际应用场景

  1. Java I/O 流

    InputStream in = new BufferedInputStream(
                      new FileInputStream("test.txt"));

  2. GUI组件装饰

    • 滚动条装饰基础组件

    • 边框装饰可视化组件

  3. Web开发

    // Servlet API示例
    HttpServletRequest wrappedRequest = 
        new RequestWrapper(originalRequest);

  4. Spring Security

    SecurityContext context = SecurityContextHolder.getContext();
    Authentication auth = new UsernamePasswordAuthenticationToken(...);
    context.setAuthentication(auth);


最佳实践建议

  1. 适用场景

    • 需要动态、透明地添加职责

    • 不适合用子类扩展的情况(如需要大量组合)

  2. 注意事项

    • 装饰器接口必须与组件接口一致

    • 避免创建过多小对象(可能影响性能)

    • 与代理模式区别:装饰器侧重功能增强,代理侧重访问控制

  3. Java实现技巧

    // 使用lambda简化装饰器(Java8+)
    Function<Coffee, Coffee> decorator = coffee -> {
        System.out.println("添加装饰");
        return new Coffee() {
            public double getCost() { return coffee.getCost() + 0.3; }
            public String getDescription() { 
                return coffee.getDescription() + "+装饰"; 
            }
        };
    };

装饰器模式通过灵活的运行时组合,完美实现了开闭原则(对扩展开放,对修改关闭),是面向对象设计中功能扩展的重要手段。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值