设计模式6-装饰器模式

1. 概念

        装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向现有对象动态地添加功能,而无需修改其源代码。这种模式通过将对象包装在一个装饰器类的实例中来实现。装饰器类具有与原始对象相同的接口,这样客户端就无需知道装饰器和原始对象之间的区别。

装饰器模式的角色和工作原理:

  1. 组件接口(Component Interface)

    • 定义了被装饰对象和装饰器共同实现的接口或抽象类。
  2. 具体组件(Concrete Component)

    • 实现了组件接口的具体对象,可以被装饰或包装。
  3. 装饰器(Decorator)

    • 持有一个指向组件对象的引用,并实现了与组件接口相同的接口。
    • 通常是一个抽象类,其子类可以添加额外的功能。
  4. 具体装饰器(Concrete Decorator)

    • 继承自装饰器类,实现了额外的功能。
    • 在执行额外功能的同时,通过调用父类的方法来保留原始对象的行为。

装饰器模式的优点:

  • 遵循开闭原则:可以在不修改现有代码的情况下增加新功能。
  • 灵活性:可以通过组合不同的装饰器来实现不同的行为组合,而不是静态继承关系。
  • 单一职责原则:每个装饰器类实现单一功能,易于管理和维护。

装饰器模式的应用场景:

  • 动态增加功能:当需要在不改变现有对象结构的情况下,动态地添加功能或责任时,装饰器模式很有用。
  • 多层装饰:可以通过叠加多个装饰器来实现复杂的行为组合,比如 I/O 流的处理。
  • 维护已有代码:当需要在不破坏已有代码结构的前提下,修改或扩展功能时,装饰器模式可以被应用。

2. 示例

         下面是一个使用Java实现装饰器模式的示例,我们将以咖啡和装饰器为例。首先定义一个咖啡接口 Coffee 和具体的咖啡类 SimpleCoffee,然后创建装饰器抽象类 CoffeeDecorator 和具体的装饰器类 MilkDecoratorSugarDecorator

// 定义咖啡接口
interface Coffee {
    double getCost(); // 获取咖啡价格
    String getDescription(); // 获取咖啡描述
}

// 具体咖啡类
class SimpleCoffee implements Coffee {
    @Override
    public double getCost() {
        return 1.0; // 基础咖啡价格
    }

    @Override
    public String getDescription() {
        return "Simple Coffee"; // 基础咖啡描述
    }
}

// 装饰器抽象类
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();
    }
}

// 具体装饰器类:牛奶装饰器
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"; // 加牛奶的描述
    }
}

// 具体装饰器类:糖装饰器
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"; // 加糖的描述
    }
}

// 使用示例
public class DecoratorPatternExample {
    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 milkSugarCoffee = new SugarDecorator(milkCoffee);
        System.out.println("Cost: " + milkSugarCoffee.getCost() + "; Description: " + milkSugarCoffee.getDescription());
    }
}

在上面的示例中,我们首先定义了 Coffee 接口,其中包含 getCost()getDescription() 方法。然后创建了一个具体的咖啡类 SimpleCoffee,实现了 Coffee 接口。接着,定义了装饰器抽象类 CoffeeDecorator,它也实现了 Coffee 接口,并包含一个对 Coffee 对象的引用。具体的装饰器类 MilkDecoratorSugarDecorator 继承自 CoffeeDecorator,并分别扩展了咖啡的价格和描述。

DecoratorPatternExample 类的 main 方法中,我们创建了一个简单的咖啡对象 SimpleCoffee,然后使用装饰器 MilkDecoratorSugarDecorator 来动态地添加牛奶和糖。每个装饰器都会修改咖啡的价格和描述,但不改变原始咖啡对象的类结构。

这个示例展示了装饰器模式的灵活性和可扩展性,我们可以随时组合不同的装饰器来增强对象的功能,而不需要修改原始对象的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值