装饰器设计模式用法及如何扩展
装饰器设计模式是一种结构型设计模式,它允许在不修改已有对象的情况下给其添加额外的功能。
装饰器设计模式基于以下几个核心概念:
-
组件接口(Component Interface):定义了需要进行装饰的对象的共同行为。
-
具体组件(Concrete Component):实现了组件接口,是需要被装饰的对象。
-
装饰器(Decorator):实现了组件接口,同时持有一个组件对象作为成员变量,用于对组件对象进行装饰。
通过将装饰器对象包装在具体组件上,可以在运行时动态地添加额外的功能。装饰器可以与其他装饰器进行嵌套,形成一个装饰器链。
当需要给一个对象添加多个不同的功能时,可以使用装饰器设计模式。它避免了创建大量的子类来实现不同的功能组合,从而使得代码更加灵活和可扩展。
我们有一个简单的饮料店,我们需要为饮料店编写一个订单系统。订单系统需要能够计算订单的总价格,并且可以根据需要进行特定的装饰。下面是一个使用装饰器设计模式的示例代码:
首先,我们定义一个组件接口Beverage,其中包含了获取饮料描述和计算价格的方法:
public interface Beverage {
String getDescription();
double getPrice();
}
然后,我们实现具体的饮料类,比如咖啡Coffee和茶Tea,它们都实现了Beverage接口:
public class Coffee implements Beverage {
@Override
public String getDescription() {
return \"Coffee\";
}
@Override
public double getPrice() {
return 2.0;
}
}
public class Tea implements Beverage {
@Override
public String getDescription() {
return \"Tea\";
}
@Override
public double getPrice() {
return 1.5;
}
}
接下来,我们创建装饰器类CondimentDecorator,它也实现了Beverage接口,同时持有一个Beverage对象作为成员变量:
public abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
然后,我们可以创建具体的装饰器类,比如Sugar和Milk,它们都继承自CondimentDecorator:
public class Sugar extends CondimentDecorator {
public Sugar(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + \", Sugar\";
}
@Override
public double getPrice() {
return beverage.getPrice() + 0.5;
}
}
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + \", Milk\";
}
@Override
public double getPrice() {
return beverage.getPrice() + 0.8;
}
}
最后,我们可以使用这些类创建订单,例如:
Beverage coffee = new Coffee();
System.out.println(coffee.getDescription() + \": \" + coffee.getPriceWithSugar.getDescription() + \": \" + teaWithSugar.getPrice());
Beverage coffeeWithSugarAndMilk = new Sugar(new Milk(new Coffee()));
System.out.println(coffeeWithSugarAndMilk.getDescription() + \": \" + coffeeWithSugarAndMilk.getPrice());
输出结果:
Coffee: 2.0
Tea, Sugar: 2.0
Coffee, Milk, Sugar: 3.3
在这个示例中,我们使用装饰器模式给饮料对象添加了额外的功能(糖和牛奶),而不需要修改原有的饮料类。我们只需要创建具体的装饰器类,并将饮料对象传入装饰器的构造方法中,在调用getDescription和getPrice方法时,装饰器会首先调用被装饰对象相应的方法,然后添加额外的功能和价格。
通过这种方式,我们可以自由地组合和扩展各种装饰器,以满足不同的需求,同时保持代码的灵活性和可扩展性。