🎯 设计模式专栏,持续更新中, 欢迎订阅:JAVA实现设计模式
🛠️ 希望小伙伴们一键三连,有问题私信都会回复,或者在评论区直接发言
装饰者模式
文章目录
- 装饰者模式
- 🎯 核心要点:
- 例子解析:咖啡饮品系统 ☕️
- 🧩 UML结构图解释
- Java代码实现:咖啡系统
- Step 1: 定义基本组件接口
- Step 2: 实现具体的咖啡类
- Step 3: 定义装饰者基类
- Step 4: 创建具体的装饰者类
- Step 5: 使用装饰者模式创建咖啡订单
- 装饰者模式在JDK中的应用
- Java I/O 系列中的装饰者模式
- 🧠 总结:
装饰者模式,也叫装饰模式,是一种结构型设计模式。它允许通过将对象放入特殊的包装对象中来为对象添加新行为,而无需修改原始对象的代码。关键思想是“包装”,我们用装饰类将对象嵌套起来,从而动态地给对象添加功能。
🎯 核心要点:
- 对象的功能扩展:不改变现有类的结构,动态地为对象添加新的功能。
- 遵循开放-封闭原则:类应对扩展开放,对修改封闭。
- 组合代替继承:相比通过继承扩展功能,装饰模式更倾向于组合对象。
例子解析:咖啡饮品系统 ☕️
假设我们有一个基本的咖啡类,用户可以购买基本咖啡,但他们也可以通过添加配料(比如牛奶、糖、巧克力等)来丰富咖啡的口味。装饰者模式完美地符合这个需求。
🧩 UML结构图解释
- Component(组件接口):定义一个接口,表示对象的基本功能。
- ConcreteComponent(具体组件):实现基本功能的具体对象。
- Decorator(装饰者):持有一个
Component
引用,并实现Component
接口。 - ConcreteDecorator(具体装饰者):继承
Decorator
,通过组合和扩展为基本功能添加附加功能。
Java代码实现:咖啡系统
Step 1: 定义基本组件接口
public abstract class Drink {
// 描述
public String des;
// 价格
private float price = 0.0f;
/**
* 计算价格
* @return
*/
public abstract float cost();
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
Step 2: 实现具体的咖啡类
public class LongBlack extends Coffee{
public LongBlack() {
setDes("LongBlack");
setPrice(35.0f);
}
}
public class Espresso extends Coffee{
public Espresso() {
setDes("Espresso(蒸汽加压煮出的)浓咖啡");
setPrice(15.0f);
}
}
public class ShortBlack extends Coffee{
public ShortBlack() {
setDes("ShortBlack浓缩咖啡");
setPrice(20.0f);
}
}
public class DeCaf extends Coffee{
public DeCaf() {
setDes("DeCaf无咖啡因咖啡");
setPrice(6.0f);
}
}
Step 3: 定义装饰者基类
public class Decorator extends Drink {
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
/**
* 计算价格
* 调用被装饰者的价格
* @return
*/
@Override
public float cost() {
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
// obj.getDes() 输出被装饰者的信息
return des + "价格:" + getPrice() +" + " +obj.getDes() +":" + obj.getPrice();
}
}
Step 4: 创建具体的装饰者类
// 加巧克力功能的装饰器
public class ChocolateDecorator extends Decorator{
public ChocolateDecorator(Drink obj) {
super(obj);
setDes(" 巧克力 ");
setPrice(3.0f);
}
}
// 加奶
public class MilkDecorator extends Decorator{
public MilkDecorator(Drink obj) {
super(obj);
setDes("加奶");
setPrice(2.0f);
}
}
// 加糖
public class SugarDecorator extends Decorator{
public SugarDecorator(Drink obj) {
super(obj);
setDes("加糖");
setPrice(1.5f);
}
}
Step 5: 使用装饰者模式创建咖啡订单
public class CoffeeShopDemo {
public static void main(String[] args) {
Drink drink = new ShortBlack();
System.out.println("浓缩咖啡描述:" + drink.getDes());
System.out.println("浓缩咖啡价格:" + drink.cost());
System.out.println("------------------------------------------");
drink = new MilkDecorator(drink);
System.out.println("加奶的浓缩咖啡描述:" + drink.getDes());
System.out.println("加奶的浓缩咖啡价格:" + drink.cost());
System.out.println("------------------------------------------");
drink = new ChocolateDecorator(drink);
System.out.println("加奶和巧克力的浓缩咖啡描述:" + drink.getDes());
System.out.println("加奶和巧克力的浓缩咖啡价格:" + drink.cost());
}
}
装饰者模式在JDK中的应用
Java I/O 系列中的装饰者模式
Java I/O 类库是装饰者模式的经典实现之一,它通过装饰者模式增强了各种流(Stream)的功能,例如:BufferedInputStream
, DataInputStream
等类都是对 InputStream
的装饰。
关键类:InputStream
系列
InputStream
:抽象组件,定义了基础的输入操作。FileInputStream
:具体组件,提供文件流读取功能。BufferedInputStream
、DataInputStream
:具体装饰者,提供了缓存、数据类型读取等额外功能。
代码示例:
// 基本的文件输入流
InputStream fileInput = new FileInputStream("file.txt");
// 装饰为带缓存的输入流
InputStream bufferedInput = new BufferedInputStream(fileInput);
// 装饰为带数据输入功能的流
DataInputStream dataInput = new DataInputStream(bufferedInput);
int data = dataInput.readInt(); // 使用增强功能读取整型数据
BufferedInputStream
:增强了基础InputStream
,通过引入缓存机制来提高性能。DataInputStream
:增强了基础InputStream
,提供了直接读取原始数据类型(如int
、float
)的能力,而不是逐字节操作
Java I/O 是装饰者模式的经典应用,通过为流对象逐层装饰增加功能(如缓存、数据类型读写等)。
🧠 总结:
- 装饰者模式通过组合多个装饰类,为对象动态地添加功能。
- 每个装饰者对象都封装了另一个对象,可以无限扩展功能。
- 对比继承,装饰者模式更加灵活、动态。