二十三种设计模式全面解析-装饰器模式-超越继承的灵活装扮-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

在软件开发中我们经常面临需要为对象动态地添加额外的功能或属性的情况。继承是一种常见的解决方案但它有时会导致类的爆炸性增长和复杂的继承层次结构。在这种情况下装饰器模式Decorator Pattern是一种强大的设计模式能够帮助我们实现灵活的组合和装饰对象而无需依赖于继承关系。


本文将深入解析装饰器模式包括装饰器模式的基本概念、适用场景、技术要点以及详细的案例代码。让我们一起探索装饰器模式的魅力为软件设计带来全新的可能性。

1、什么是装饰器模式

装饰器模式属于结构型设计模式它允许我们在运行时动态地给对象添加新的行为或属性而无需修改其原始类。装饰器模式通过将对象包装在一个装饰器类中然后将装饰器类嵌套在其他装饰器类中从而形成一个装饰器链。


一个对象可以使用多个类的行为 包含多个指向其他对象的引用 并将各种工作委派给引用对象 继承中的对象则继承了父类的行为 它们自己能够完成这些工作。


2、适用场景

装饰器模式适用于以下情况

  • 当你需要动态地为对象添加额外的功能而不影响其他对象。
  • 当你希望通过组合而非继承来实现对象的扩展。
  • 当你有多个不同的功能组合选项并且想要避免创建大量的子类。

3、技术要点

装饰器模式的核心要点包括

  • 抽象构件Component声明封装器和被封装对象的公用接口。

  • 具体构件Concrete Component是被封装对象所属的类它定义了基础行为但装饰类可以改变这些行为。

  • 基础装饰器 (Base Decorator) 拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明为通用部件接口这样它就可以引用具体的部件和装饰。装饰基类会将所有操作委派给被封装的对象。

  • 具体装饰器 (Concrete Decorators)定义了可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法并在调用父类方法之前或之后进行额外的行为。


4、案例代码

考虑一个咖啡店的订单系统我们有不同类型的咖啡如浓缩咖啡和拿铁咖啡以及额外的调料如牛奶和糖。为了实现灵活性我们可以使用装饰器模式来动态地为咖啡对象添加调料。


首先我们定义抽象构件Coffee和具体构件Espresso和Latte

// 抽象构件 - 咖啡
interface Coffee {
    String getDescription();
    double getCost();
}

// 具体构件 - 浓缩咖啡
class Espresso implements Coffee {
    @Override
    public String getDescription() {
        return "浓缩咖啡";
    }

    @Override
    public double getCost() {
        return 2.0;
    }
}

// 具体构件 - 拿铁咖啡
class Latte implements Coffee {
    @Override
    public String getDescription() {
        return "拿铁咖啡";
    }

    @Override
    public double getCost() {
        return 3.0;
    }
}


然后我们定义基础装饰器类CoffeeDecorator和具体装饰器类MilkDecorator和SugarDecorator

// 装饰器 - 咖啡装饰器
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();
    }
}

// 具体装饰器 - 牛奶装饰器
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return coffee.getDescription() + "加牛奶";
    }

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

// 具体装饰器 - 糖装饰器
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return coffee.getDescription() + "加糖";
    }

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

最后我们可以使用装饰器模式来创建不同类型的咖啡并动态地添加调料

public class Main {
    public static void main(String[] args) {
        // 创建浓缩咖啡
        Coffee espresso = new Espresso();
        System.out.println(espresso.getDescription() + "价格" + espresso.getCost());

        // 创建拿铁咖啡
        Coffee latte = new Latte();
        System.out.println(latte.getDescription() + "价格" + latte.getCost());

        // 创建加牛奶的浓缩咖啡
        Coffee espressoWithMilk = new MilkDecorator(new Espresso());
        System.out.println(espressoWithMilk.getDescription() + "价格" + espressoWithMilk.getCost());

        // 创建加糖的拿铁咖啡
        Coffee latteWithSugar = new SugarDecorator(new Latte());
        System.out.println(latteWithSugar.getDescription() + "价格" + latteWithSugar.getCost());
    }
}

输出结果

浓缩咖啡价格2.0
拿铁咖啡价格3.0
浓缩咖啡加牛奶价格2.5
拿铁咖啡加糖价格3.2

通过装饰器模式我们可以动态地为咖啡对象添加不同的调料而不需要修改原始的咖啡类。这种灵活性使得我们能够轻松地创建各种组合并且可以随时添加或删除调料。


然而装饰器模式并不仅限于咖啡店的订单系统。它在许多其他领域中都有广泛的应用例如图形用户界面GUI框架、输入输出流处理等。在后续的博文中我们将深入探讨装饰器模式的更多应用场景和技巧让我们拭目以待


敬请期待我们下一篇博文将为您揭开更多关于装饰器模式的神秘面纱。


好了今天的分享到此结束。如果觉得我的博文帮到了您您的点赞和关注是对我最大的支持。如遇到什么问题可评论区留言。


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6