Java设计模式之装饰器(Decorator)模式

装饰器(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

这是因为我们创建了一个基础咖啡对象,并使用装饰器对象依次包装它,以扩展咖啡的配料和价格。

装饰器模式的具体应用

  1. Java IO:Java的输入输出流(IO)框架使用了装饰器模式。InputStream和OutputStream是抽象基类,而具体的输入输出流类如FileInputStream、ByteArrayInputStream等都是装饰器类的子类。这种设计允许对输入输出流进行递归式的装饰,以扩展其功能和行为。

  2. Spring框架:Spring框架中的AOP(面向切面编程)功能使用了装饰器模式。通过在运行时使用动态代理,它可以在方法调用前后插入额外的行为,如日志记录、性能监控等。

  3. Servlet过滤器:Java Servlet中的过滤器功能使用了装饰器模式。Servlet过滤器可以在请求到达Servlet之前或者响应返回给客户端之前,对请求和响应进行处理和修改。

  4. Guava库:Google的Guava库中的许多工具类和方法使用了装饰器模式。例如,Guava的Collections类提供了许多静态方法对集合进行装饰,如unmodifiableCollection、synchronizedCollection等。

总结

装饰器(Decorator)模式是一种结构型设计模式,它允许动态地将新功能添加到对象中,同时又不改变其结构。装饰器模式基于组合而非继承原则,通过递归和委托来创建具有新功能的对象。装饰器模式适用于需要在运行时扩展对象功能的情况,而不希望生成大量的子类。在实际开发中,我们可以利用装饰器模式来为现有的类或框架添加额外的功能,同时保持代码的灵活性和可维护性。

关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员‍‍!

你可能感兴趣的:(Java系列之设计模式,java,设计模式,装饰器模式)