常用设计模式6:装饰器模式(Java)

装饰器模式(Decorator Pattern)

1. 简介

装饰器模式是一种结构型设计模式,它允许通过将对象放入包含行为的特殊封装对象中来为原对象动态地添加新的行为。

2. 为什么使用装饰器模式?

  • 动态添加功能:可以在运行时动态地给对象添加功能,而不需要修改原有代码。
  • 遵循开闭原则:可以在不修改现有对象结构的情况下,使用组合来扩展对象的功能。
  • 灵活性:相比于继承,装饰器提供了更加灵活的扩展方式。
  • 避免类爆炸:在需要大量功能组合的情况下,可以避免类的数量剧增。

3. 装饰器模式的结构

装饰器模式主要包含以下角色:

  1. Component:抽象构件,定义了对象的接口。
  2. ConcreteComponent:具体构件,定义了具体的对象。
  3. Decorator:抽象装饰类,持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
  4. ConcreteDecorator:具体装饰类,负责向构件添加新的职责。

4. Java 实现示例

下面通过一个简单的咖啡订单系统来说明装饰器模式:

4.1 定义抽象构件

public interface Coffee {
    double getCost();
    String getDescription();
}

4.2 实现具体构件

public class SimpleCoffee implements Coffee {
    @Override
    public double getCost() {
        return 1;
    }

    @Override
    public String getDescription() {
        return "Simple coffee";
    }
}

4.3 定义抽象装饰类

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    @Override
    public double getCost() {
        return decoratedCoffee.getCost();
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}

4.4 实现具体装饰类

public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.5;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", milk";
    }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.2;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", sugar";
    }
}

4.5 客户端代码

public class CoffeeShop {
    public static void main(String[] args) {
        Coffee simpleCoffee = new SimpleCoffee();
        System.out.println("Cost: " + simpleCoffee.getCost() + "; Description: " + simpleCoffee.getDescription());

        Coffee milkCoffee = new MilkDecorator(simpleCoffee);
        System.out.println("Cost: " + milkCoffee.getCost() + "; Description: " + milkCoffee.getDescription());

        Coffee sweetMilkCoffee = new SugarDecorator(milkCoffee);
        System.out.println("Cost: " + sweetMilkCoffee.getCost() + "; Description: " + sweetMilkCoffee.getDescription());
    }
}

5. 装饰器模式的优缺点

优点:

  • 比静态继承更灵活。
  • 避免了功能类的膨胀。
  • 符合开闭原则。
  • 可以动态地增加或删除对象的职责。

缺点:

  • 会产生很多小对象,增加系统的复杂性。
  • 装饰链的调试可能会比较困难。

6. 适用场景

  • 需要在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能可以动态地撤销。
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

7. 总结

装饰器模式提供了一种灵活的替代子类化以扩展功能的方法。它可以在不改变原有对象结构的情况下动态地给一个对象增加一些额外的职责。这种模式在处理不断变化的需求时特别有用,允许系统随着需求的变化而不断地扩展,而不需要修改现有的代码。然而,过度使用装能会导致系统变得复杂难以理解和维护,因此在使用时需要权衡利弊。

posted @ 2024-08-06 22:10  KenWan  阅读(78)  评论(0)    收藏  举报