装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在不改变原有对象结构的情况下,动态地给对象添加额外的功能。装饰器模式通过将对象包装在一个装饰器类中,从而为对象添加新的行为或责任。
核心思想:
定义一个抽象组件(Component)接口,其中包含了一些核心的操作方法,是具体组件和装饰器共同实现的接口。
- 具体组件(ConcreteComponent)是实现了抽象组件接口的具体对象,是被装饰的原始对象。
- 抽象装饰器(Decorator)是抽象组件的子类,包含一个指向抽象组件的引用,同时实现了抽象组件接口。它可以在调用原有方法之前或之后添加新的行为,以扩展原有对象的功能。
- 具体装饰器(ConcreteDecorator)是具体组件的装饰器,它扩展了抽象装饰器,并为组件添加新的行为。
示例:
假设我们有一个简单的咖啡店程序,其中有一个抽象咖啡(Coffee)接口和具体咖啡类(Espresso、Latte),我们想要为咖啡添加额外的配料(牛奶、糖),可以使用装饰器模式来实现。
// 抽象组件:咖啡
interface Coffee {
double getCost();
String getDescription();
}
// 具体组件:浓缩咖啡
class Espresso implements Coffee {
@Override
public double getCost() {
return 2.0;
}
@Override
public String getDescription() {
return "浓缩咖啡";
}
}
// 具体组件:拿铁咖啡
class Latte implements Coffee {
@Override
public double getCost() {
return 2.5;
}
@Override
public String getDescription() {
return "拿铁咖啡";
}
}
// 抽象装饰器:咖啡配料
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public double getCost() {
return coffee.getCost();
}
@Override
public String getDescription() {
return coffee.getDescription();
}
}
// 具体装饰器:牛奶
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.3;
}
@Override
public String getDescription() {
return super.getDescription() + ", 加糖";
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Coffee espresso = new Espresso();
Coffee latteWithMilk = new MilkDecorator(new Latte());
Coffee latteWithMilkAndSugar = new SugarDecorator(new MilkDecorator(new Latte()));
System.out.println("Espresso: " + espresso.getDescription() + ", 价格:" + espresso.getCost());
System.out.println("Latte with milk: " + latteWithMilk.getDescription() + ", 价格:" + latteWithMilk.getCost());
System.out.println("Latte with milk and sugar: " + latteWithMilkAndSugar.getDescription() + ", 价格:" + latteWithMilkAndSugar.getCost());
}
}