装饰器模式:动态给对象增加额外职责,不修改原有类代码,通过包装原有对象实现功能增强,Java IO 就是典型装饰器模式。
核心角色:
抽象组件 (Component):定义被装饰对象和装饰器共同接口
具体组件 (ConcreteComponent):原始被装饰对象
抽象装饰器 (Decorator):持有组件引用,实现组件接口,包装原始对象
具体装饰器 (ConcreteDecorator):扩展额外功能
完整示例代码
// 1.抽象组件:咖啡接口
interface Coffee {
// 获取描述
String getDescription();
// 获取价格
double cost();
}
// 2.具体组件:基础黑咖啡(被装饰的原始对象)
class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "黑咖啡";
}
@Override
public double cost() {
return 10.0;
}
}
// 3.抽象装饰器:咖啡装饰器,必须实现Coffee,持有Coffee成员
abstract class CoffeeDecorator implements Coffee {
// 持有被装饰对象
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
// 4.具体装饰器1:加牛奶
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " +牛奶";
}
@Override
public double cost() {
return coffee.cost() + 2.5;
}
}
// 具体装饰器2:加糖
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " +糖";
}
@Override
public double cost() {
return coffee.cost() + 1.0;
}
}
// 具体装饰器3:加奶泡
class FoamDecorator extends CoffeeDecorator {
public FoamDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " +奶泡";
}
@Override
public double cost() {
return coffee.cost() + 3.0;
}
}
// 测试客户端
public class DecoratorDemo {
public static void main(String[] args) {
// 基础咖啡
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + ",价格:" + coffee.cost());
// 动态加牛奶
Coffee milkCoffee = new MilkDecorator(coffee);
System.out.println(milkCoffee.getDescription() + ",价格:" + milkCoffee.cost());
// 继续叠加:黑咖啡+牛奶+糖
Coffee milkSugarCoffee = new SugarDecorator(milkCoffee);
System.out.println(milkSugarCoffee.getDescription() + ",价格:" + milkSugarCoffee.cost());
// 多重装饰:黑咖啡+牛奶+糖+奶泡
Coffee fullCoffee = new FoamDecorator(new SugarDecorator(new MilkDecorator(new SimpleCoffee())));
System.out.println(fullCoffee.getDescription() + ",价格:" + fullCoffee.cost());
}
}
输出结果
黑咖啡,价格:10.0
黑咖啡 +牛奶,价格:12.5
黑咖啡 +牛奶 +糖,价格:13.5
黑咖啡 +牛奶 +糖 +奶泡,价格:16.5
关键点说明
装饰器和被装饰对象实现同一个接口,保证可以互相替换;
抽象装饰器持有组件对象,把请求委托给原始对象,再叠加自己逻辑;
可以无限嵌套装饰,动态组合功能,不用写大量继承子类;
和继承区别:继承是静态编译期扩展;装饰器是运行时动态包装对象。
Java 原生 IO 中的装饰器对照
// FileInputStream:原始组件
FileInputStream fis = new FileInputStream("test.txt");
// BufferedInputStream:装饰器,增加缓冲功能
BufferedInputStream bis = new BufferedInputStream(fis);
FileInputStream→ ConcreteComponentFilterInputStream→ 抽象 DecoratorBufferedInputStream/DataInputStream→ 具体 Decorator
优缺点
✅ 优点
比继承更灵活,运行时动态增删功能
遵循开闭原则,新增装饰不需要修改原有代码
❌ 缺点
会产生很多小的装饰器类,增加代码复杂度
对象多层包装,调试稍微麻烦
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问