装饰者模式是一种结构型设计模式,它允许在不改变对象结构的情况下,动态地添加行为或修改现有行为。在该模式中,通常将核心对象称为“组件”,并且将新增的行为称为“装饰者”。
使用装饰者模式的好处是可以将对象的功能拆分成多个小的、单一的职责,从而使每个职责都可以进行独立的扩展和修改,而不会对其他职责造成影响。此外,装饰者模式还可以避免使用继承带来的类爆炸问题,使得代码更加灵活和易于维护。
假设我们有一个咖啡店,我们需要在不改变原有咖啡的基础上,为顾客提供添加调料的服务。我们首先定义一个咖啡接口(Component),它定义了咖啡的基本行为:
代码语言:javascript复制public interface Coffee {
String getDescription();
double getCost();
}
然后,我们实现一个具体的咖啡类(ConcreteComponent),它实现了咖啡接口,并提供了基本的咖啡信息:
代码语言:javascript复制public class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double getCost() {
return 1.0;
}
}
接下来,我们定义一个装饰者抽象类(Decorator),它也实现了咖啡接口,但是它不直接提供咖啡服务,而是将服务委托给其它的组件。我们需要注意的是,装饰者类中需要保留一个对原有组件的引用。
代码语言:javascript复制public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double getCost() {
return coffee.getCost();
}
}
现在,我们可以定义具体的装饰者类,例如加牛奶、加糖等:
代码语言:javascript复制public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() ", Milk";
}
@Override
public double getCost() {
return coffee.getCost() 0.5;
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() ", Sugar";
}
@Override
public double getCost() {
return coffee.getCost() 0.3;
}
}
最后,我们可以通过如下方式来使用装饰者模式:
代码语言:javascript复制public class Main {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() " $" coffee.getCost());
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() " $" coffee.getCost());
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() " $" coffee.getCost());
}
}
在这个例子中,我们首先创建了一个简单咖啡对象,然后依次为其添加牛奶和糖装饰器。每次添加装饰器都会修改咖啡的描述和价格,但是并没有改变原有咖啡对象的结构。
输出结果如下:
代码语言:javascript复制Simple Coffee $1.0
Simple Coffee, Milk $1.5
Simple Coffee, Milk, Sugar $1.8
可以看到,我们通过装饰者模式,成功地为咖啡店提供了添加调料的服务,而且这个服务可以根据需要随意扩展。