装饰器模式是一种结构型设计模式,它允许动态地将责任附加到对象上。装饰器模式是通过创建一个包装对象,也就是装饰器,来包裹真实对象,从而实现对真实对象的功能增强。装饰器模式可以在不修改原有对象的情况下,动态地添加功能。
装饰器模式通常由以下几个组件组成:
1.Component(组件接口):定义了一个对象接口,可以给这些对象动态地添加职责。
2.ConcreteComponent(具体组件):实现了组件接口,是被装饰的对象。
3.Decorator(装饰器抽象类):持有一个指向组件对象的引用,并实现了组件接口。通常是一个抽象类,用于定义装饰器的基本行为。
4.ConcreteDecorator(具体装饰器):扩展了装饰器抽象类,实现了具体的装饰功能。
开始上代码
首先我们定义一个咖啡
// 组件接口
interface Coffee {
double cost();
String getDescription();
}
咖啡分很多种类,我们先来一个浓缩咖啡
// 具体组件 - 浓缩咖啡
class Espresso implements Coffee {
@Override
public double cost() {
return 1.5;
}
@Override
public String getDescription() {
return "Espresso";
}
}
然后我觉得浓缩咖啡有点苦,所以我想加点糖和牛奶
所以这里我们要开始上装饰器了
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public double cost() {
return coffee.cost();
}
@Override
public String getDescription() {
return coffee.getDescription();
}
}
加奶的装饰器
// 具体装饰器 - 加牛奶
class Milk extends CoffeeDecorator {
public Milk(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 0.5;
}
@Override
public String getDescription() {
return super.getDescription() + ", Milk";
}
}
加糖的装饰器
// 具体装饰器 - 加糖
class Sugar extends CoffeeDecorator {
public Sugar(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 0.2;
}
@Override
public String getDescription() {
return super.getDescription() + ", Sugar";
}
}
然后测试一下
public class Test {
public static void main(String[] args) {
// 点一杯浓缩咖啡
Coffee espresso = new Espresso();
System.out.println("Espresso: " + espresso.getDescription() + " - Cost: $" + espresso.cost());
// 加牛奶
Coffee espressoWithMilk = new Milk(espresso);
System.out.println("Espresso with Milk: " + espressoWithMilk.getDescription() + " - Cost: $" + espressoWithMilk.cost());
// 加糖
Coffee espressoWithSugar = new Sugar(espresso);
System.out.println("Espresso with Sugar: " + espressoWithSugar.getDescription() + " - Cost: $" + espressoWithSugar.cost());
// 加牛奶和糖
Coffee espressoWithMilkAndSugar = new Sugar(new Milk(espresso));
System.out.println("Espresso with Milk and Sugar: " + espressoWithMilkAndSugar.getDescription() + " - Cost: $" + espressoWithMilkAndSugar.cost());
}
}
运行结果
可以发现这个模式很好理解,看起来也比较实用的样子