装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你在不改变对象结构的情况下,动态地将新功能附加到对象上。装饰器模式通过创建一个包装对象来实现这一目的,该包装对象包含了原始对象,并在其上添加了额外的行为。
在装饰器模式中,有四个主要的角色:
- 抽象组件(Component):定义了装饰器和具体组件的共同接口,可以是抽象类或接口。
- 具体组件(Concrete Component):实现了抽象组件的接口,是被装饰的原始对象。
- 抽象装饰器(Decorator):继承自抽象组件,持有一个抽象组件的引用,并在其上添加额外的行为。
- 具体装饰器(Concrete Decorator):继承自抽象装饰器,实现了额外的行为。
下面是一个简单的示例,展示了如何使用装饰器模式来扩展一个咖啡店的咖啡选择:
// 抽象组件
interface Coffee {String getDescription();double getCost();
}// 具体组件
class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double getCost() {return 1.0;}
}// 抽象装饰器
abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double getCost() {return decoratedCoffee.getCost();}
}// 具体装饰器
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Milk";}@Overridepublic double getCost() {return decoratedCoffee.getCost() + 0.5;}
}// 具体装饰器
class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Sugar";}@Overridepublic double getCost() {return decoratedCoffee.getCost() + 0.2;}
}// 使用示例
public class DecoratorPatternExample {public static void main(String[] args) {// 创建一个简单咖啡对象Coffee coffee = new SimpleCoffee();System.out.println("Description: " + coffee.getDescription());System.out.println("Cost: $" + coffee.getCost());// 使用装饰器来添加牛奶和糖Coffee decoratedCoffee = new MilkDecorator(new SugarDecorator(coffee));System.out.println("Description: " + decoratedCoffee.getDescription());System.out.println("Cost: $" + decoratedCoffee.getCost());}
}
在上面的示例中,抽象组件是Coffee
接口,具体组件是SimpleCoffee
类,抽象装饰器是CoffeeDecorator
类,具体装饰器有MilkDecorator
和SugarDecorator
类。我们可以通过组合不同的装饰器来动态地扩展咖啡的描述和价格,而不需要修改原始的咖啡对象。
运行上述示例代码,输出如下:
Description: Simple Coffee
Cost: $1.0
Description: Simple Coffee, Sugar, Milk
Cost: $1.7
可以看到,通过装饰器模式,我们成功地在不改变原始咖啡对象的情况下,动态地添加了牛奶和糖的描述和价格。这样的设计模式使得代码更加灵活、可扩展,并符合开闭原则。