【设计模式】装饰模式

1.模式简述
比如我们去咖啡店点了一杯咖啡,可以选择加糖,加牛奶等辅料。每加一种辅料。价格都会相应的增加,且描述也会更新。原味咖啡:10元,加牛奶:+2元,总价12元。加糖:+1元,总价13元。装饰器模式就像一层层包装咖啡,每一层包装新的功能(辅料),不需要修改咖啡本身的代码。

适用场景:

  1. 动态扩展对象的功能,且不想通过继承生成大量子类。
  2. 需要为对象添加临时或可选的职责。
  3. 无法通过继承扩展功能(例如类被 final 修饰)。

优点:

  1. 灵活扩展:无需修改原有代码,符合开闭原则。
  2. 避免子类爆炸:通过组合替代继承,减少类数量。

缺点:

  1. 增加代码复杂度:需要定义大量小类。
  2. 多层装饰时,调试困难(包装层次多)。

2.示例代码
类图
【设计模式】装饰模式_第1张图片
代码

// 1. 定义咖啡接口
interface Coffee {
double getCost();
String getDescription();
}


// 2. 基础咖啡实现
class SimpleCoffee implements Coffee {
@Override
public double getCost() { return 10.0; }
@Override
public String getDescription() { return "原味咖啡"; }
}


// 3. 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; }
}


// 4. 具体装饰器:加牛奶
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) { super(coffee); }
@Override
public double getCost() { return decoratedCoffee.getCost() + 2.0; }
@Override
public String getDescription() { return decoratedCoffee.getDescription() + " + 牛奶"; }
}


// 5. 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) { super(coffee); }
@Override
public double getCost() { return decoratedCoffee.getCost() + 1.0; }
@Override
public String getDescription() { return decoratedCoffee.getDescription() + " + 糖"; }
}


// 6. 客户端使用
public class Main {
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());
}
}

3.实际案例

Java IO 流。JavaBufferedReaderFileReader 是装饰器模式的经典应用。
import java.io.*;


public class IOExample {
public static void main(String[] args) {
try (Reader reader = new BufferedReader(new FileReader("test.txt"))) {
int data;
while ((data = reader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

解释:
FileReader 负责读取文件内容。

BufferedReader 作为装饰器,为其添加缓冲功能(提升性能)。

两者都继承自 Reader,符合装饰器模式的结构。

你可能感兴趣的:(设计模式,设计模式,java)