装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向现有对象动态地添加额外的功能,同时又不改变其接口。该模式通过创建一个包装器类,将原始对象包装在其中,并在保持原始对象方法签名的同时,提供了额外的功能。
在装饰器模式中,有以下几个角色:
- 抽象组件(Component):定义了被装饰对象和装饰对象的共同接口。
- 具体组件(ConcreteComponent):实现了抽象组件接口,是被装饰的原始对象。
- 抽象装饰器(Decorator):继承了抽象组件,并持有一个抽象组件的引用,以便调用原始对象的方法。
- 具体装饰器(ConcreteDecorator):实现了抽象装饰器接口,通过对原始对象的包装,添加额外的功能。
下面是一个示例,以咖啡店为例,展示装饰器模式的使用:
首先,我们定义一个抽象组件接口 Coffee
,它包含了制作咖啡的方法 brew()
:
public interface Coffee {
void brew();
}
然后,我们创建一个具体组件 SimpleCoffee
,实现了 Coffee
接口:
public class SimpleCoffee implements Coffee {
@Override
public void brew() {
System.out.println("Brewing a simple coffee");
}
}
接下来,我们定义一个抽象装饰器接口 CoffeeDecorator
,它继承了 Coffee
接口,并持有一个 Coffee
对象的引用:
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
然后,我们创建具体装饰器类 MilkDecorator
,它继承了 CoffeeDecorator
,并实现了 brew()
方法,在原始对象的基础上添加了牛奶的功能:
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public void brew() {
coffee.brew();
addMilk();
}
private void addMilk() {
System.out.println("Adding milk to the coffee");
}
}
最后,我们可以使用装饰器模式来制作不同的咖啡,例如:
public class Main {
public static void main(String[] args) {
// 创建一个简单的咖啡
Coffee simpleCoffee = new SimpleCoffee();
simpleCoffee.brew(); // Output: Brewing a simple coffee
// 使用装饰器给咖啡添加牛奶
Coffee coffeeWithMilk = new MilkDecorator(simpleCoffee);
coffeeWithMilk.brew();
// Output:
// Brewing a simple coffee
// Adding milk to the coffee
}
}
在上面的示例中,我们通过创建 MilkDecorator
装饰器来给 SimpleCoffee
对象添加了牛奶功能,而不需要修改原始对象的代码。这样,我们可以根据需要动态地添加或移除不同的装饰器,实现了对咖啡对象的灵活扩展。