装饰器(Decorator)设计模式允许动态地将新功能添加到对象中,同时又不改变其结构。
装饰器(Decorator)模式通过将对象进行包装,以扩展其功能,而不需要修改其原始类。装饰器模式基于组合而非继承的原则,通过递归和委托来创建具有新功能的对象。
装饰器(Decorator)模式适用于以下情况:
下面是一个简单的示例,我们将使用装饰器模式来扩展一个咖啡店中的咖啡品种,如添加牛奶、糖等。我们将创建一个基础的咖啡接口,然后使用装饰器类来扩展可选的配料。下面是代码实现:
// 咖啡接口
interface Coffee {
String getIngredients(); // 获取咖啡配料
double getPrice(); // 获取咖啡价格
}
// 基础咖啡类
class SimpleCoffee implements Coffee {
public String getIngredients() {
return "Coffee";
}
public double getPrice() {
return 2.0;
}
}
// 咖啡装饰器基类
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
public String getIngredients() {
return coffee.getIngredients();
}
public double getPrice() {
return coffee.getPrice();
}
}
// 牛奶咖啡装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public String getIngredients() {
return coffee.getIngredients() + ", Milk";
}
public double getPrice() {
return coffee.getPrice() + 0.5;
}
}
// 糖咖啡装饰器
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
public String getIngredients() {
return coffee.getIngredients() + ", Sugar";
}
public double getPrice() {
return coffee.getPrice() + 0.3;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 创建基础咖啡对象
Coffee baseCoffee = new SimpleCoffee();
System.out.println("基础咖啡: " + baseCoffee.getIngredients() + ", 价格: " + baseCoffee.getPrice());
// 添加牛奶
Coffee milkCoffee = new MilkDecorator(baseCoffee);
System.out.println("加入牛奶: " + milkCoffee.getIngredients() + ", 价格: " + milkCoffee.getPrice());
// 添加糖
Coffee sugarCoffee = new SugarDecorator(milkCoffee);
System.out.println("加入糖: " + sugarCoffee.getIngredients() + ", 价格: " + sugarCoffee.getPrice());
}
}
在上述代码中,我们定义了一个咖啡接口(Coffee),以及一个基础咖啡类(SimpleCoffee)实现了这个接口。然后,我们创建了一个咖啡装饰器基类(CoffeeDecorator),它也实现了咖啡接口,并通过构造函数接收一个咖啡对象。接下来,我们创建了两个具体的装饰器类:牛奶装饰器(MilkDecorator)和糖装饰器(SugarDecorator),它们都继承自咖啡装饰器基类,并分别扩展了咖啡的配料和价格。
最后,在客户端代码中,我们实例化了一个基础咖啡对象,然后使用装饰器类将其包装,以便于在咖啡中添加牛奶和糖。我们可以通过调用装饰器对象的 getIngredients() 和 getPrice() 方法来获取装饰后的咖啡的配料和价格。
运行上述代码,您应该会得到以下输出结果:
基础咖啡: Coffee, 价格: 2.0
加入牛奶: Coffee, Milk, 价格: 2.5
加入糖: Coffee, Milk, Sugar, 价格: 2.8
这是因为我们创建了一个基础咖啡对象,并使用装饰器对象依次包装它,以扩展咖啡的配料和价格。
Java IO:Java的输入输出流(IO)框架使用了装饰器模式。InputStream和OutputStream是抽象基类,而具体的输入输出流类如FileInputStream、ByteArrayInputStream等都是装饰器类的子类。这种设计允许对输入输出流进行递归式的装饰,以扩展其功能和行为。
Spring框架:Spring框架中的AOP(面向切面编程)功能使用了装饰器模式。通过在运行时使用动态代理,它可以在方法调用前后插入额外的行为,如日志记录、性能监控等。
Servlet过滤器:Java Servlet中的过滤器功能使用了装饰器模式。Servlet过滤器可以在请求到达Servlet之前或者响应返回给客户端之前,对请求和响应进行处理和修改。
Guava库:Google的Guava库中的许多工具类和方法使用了装饰器模式。例如,Guava的Collections类提供了许多静态方法对集合进行装饰,如unmodifiableCollection、synchronizedCollection等。
装饰器(Decorator)模式是一种结构型设计模式,它允许动态地将新功能添加到对象中,同时又不改变其结构。装饰器模式基于组合而非继承原则,通过递归和委托来创建具有新功能的对象。装饰器模式适用于需要在运行时扩展对象功能的情况,而不希望生成大量的子类。在实际开发中,我们可以利用装饰器模式来为现有的类或框架添加额外的功能,同时保持代码的灵活性和可维护性。
关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员!