当前位置: 首页 > article >正文

结构型模式4.装饰器模式

结构型模式

  1. 适配器模式(Adapter Pattern)
  2. 桥接模式(Bridge Pattern)
  3. 组合模式(Composite Pattern)
  4. 装饰器模式(Decorator Pattern)
  5. 外观模式(Facade Pattern)
  6. 享元模式(Flyweight Pattern)
  7. 代理模式(Proxy Pattern)

装饰器模式(Decorator Pattern)是一种结构型设计模式,旨在动态地给一个对象添加额外的功能,而不需要修改其结构。装饰器模式通过使用组合(而非继承)来扩展对象的功能,允许你在运行时对对象进行扩展。

装饰器模式的核心思想:

  • 不改变对象的原有功能,而是在原有功能的基础上增加新的功能
  • 通过将装饰功能封装在装饰器类中,使得功能的增加和修改更加灵活。
  • 装饰器模式通常与继承相对,继承会通过扩展类来增加功能,而装饰器模式是通过组合不同的装饰器对象来增强功能。

主要角色:

  1. Component(组件):定义了一个接口,通常是一个抽象类或者接口,规定了被装饰的对象和装饰器的共同接口。
  2. ConcreteComponent(具体组件):实现了Component接口的基本功能,是被装饰的目标对象。
  3. Decorator(装饰器):是一个抽象类,持有一个Component对象,并在其功能上进行扩展。它继承了Component接口,并将所有方法委托给实际的Component对象。
  4. ConcreteDecorator(具体装饰器):继承自Decorator,负责具体的功能扩展(例如添加新功能或修改现有功能)。

装饰器模式的示例:咖啡店

假设我们要设计一个咖啡的销售系统,其中有不同种类的咖啡(例如:单纯的黑咖啡、加了牛奶的咖啡、加了糖的咖啡等),每种咖啡在基础上都有不同的装饰。我们可以使用装饰器模式来动态地为咖啡添加不同的配料。

// 组件接口,所有的咖啡都实现这个接口
public interface Coffee {
    double cost(); // 计算价格
    String ingredients(); // 获取配料信息
}

// 具体组件,代表普通的黑咖啡
public class BlackCoffee implements Coffee {
    @Override
    public double cost() {
        return 5.0; // 黑咖啡的基础价格
    }

    @Override
    public String ingredients() {
        return "Black Coffee"; // 黑咖啡的配料
    }
}

// 装饰器,持有一个Coffee对象,并且可以增强其功能
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee; // 持有一个咖啡对象

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

    @Override
    public double cost() {
        return coffee.cost(); // 委托给被装饰的咖啡对象
    }

    @Override
    public String ingredients() {
        return coffee.ingredients(); // 委托给被装饰的咖啡对象
    }
}


// 装饰器1:添加牛奶
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return coffee.cost() + 2.0; // 加牛奶的价格
    }

    @Override
    public String ingredients() {
        return coffee.ingredients() + ", Milk"; // 牛奶的配料
    }
}

// 装饰器2:添加糖
public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return coffee.cost() + 1.0; // 加糖的价格
    }

    @Override
    public String ingredients() {
        return coffee.ingredients() + ", Sugar"; // 糖的配料
    }
}

public class Client {
    public static void main(String[] args) {
        // 创建一个黑咖啡
        Coffee coffee = new BlackCoffee();
        System.out.println("Cost: " + coffee.cost()); // 输出:5.0
        System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee

        // 给黑咖啡添加牛奶
        coffee = new MilkDecorator(coffee);
        System.out.println("Cost: " + coffee.cost()); // 输出:7.0
        System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee, Milk

        // 给已经添加牛奶的咖啡再添加糖
        coffee = new SugarDecorator(coffee);
        System.out.println("Cost: " + coffee.cost()); // 输出:8.0
        System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee, Milk, Sugar
    }
}

解释:

  • Component(Coffee):定义了咖啡的基础功能,所有的咖啡类都实现了这个接口,提供 cost() 和 ingredients() 方法。
  • ConcreteComponent(BlackCoffee):表示一种具体的咖啡(黑咖啡),实现了 Coffee 接口。
  • Decorator(CoffeeDecorator):是一个抽象类,持有一个 Coffee 对象,允许在此基础上添加新功能。
  • ConcreteDecorator(MilkDecorator 和 SugarDecorator):具体装饰器,分别为咖啡添加牛奶和糖。它们在原有功能的基础上进行扩展。

装饰器模式的优缺点:

优点:
  1. 增强灵活性:装饰器模式允许动态地向对象添加功能,而不需要修改原有对象的代码。这种方式比继承更灵活。
  2. 减少子类的创建:通过装饰器模式,我们不需要为每一种不同的组合创建一个子类,而是通过不同的装饰器组合出所需的功能。
  3. 符合开闭原则:装饰器模式遵循开闭原则,即可以对功能进行扩展而不需要修改原有代码。
缺点:
  1. 装饰器过多时,系统会变得很复杂:如果装饰器链太长,可能会造成代码的复杂度增加,使得调试和理解变得更加困难。
  2. 可能导致过多的小对象:每个装饰器本身就是一个对象,因此在复杂的系统中,可能会创建大量的小对象,增加内存开销。

总结:

装饰器模式通过将功能与对象的实现分离,使得我们能够在运行时动态地增加对象的功能,而不需要修改对象本身。它能够灵活地扩展对象功能,减少了子类数量,提升了系统的灵活性和可维护性。


http://www.kler.cn/a/472862.html

相关文章:

  • 嵌入式系统 (2.嵌入式硬件系统基础)
  • Mac-docker配置
  • 计算机网络基础——网络协议
  • 计算机毕业设计Python中华古诗词知识图谱可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析模型 自然语言处理NLP 机器学习 深度学习
  • 装修房子,你会选购灯和搭配灯光吗?
  • asammdf python库解析MF4文件(一)cut and filter
  • 枫清科技高雪峰: Data-Centric新范式开启,知识引擎+大模型双轮驱动企业智能化
  • Python里JSON orjson ujson在json.loads有什么区别?
  • 性能测试03|JMeter:断言、关联、web脚本录制
  • c++ 17 constexpr
  • conda+jupyter+pycharm:如何在Windows conda环境下运行jupyter并使用浏览器或者pycharm运行.ipynb
  • 开源一款简单易用的键盘音效工具
  • el-table 多级表头
  • 域名反查IP多种方式
  • 【Linux基础指令】第一期
  • 高频 SQL 50 题(基础版)_197. 上升的温度
  • cursor试用出现:Too many free trial accounts used on this machine 的解决方法
  • html 前端进行浮动布局设置
  • Go跨平台UI开发之wails的使用(1)
  • Lua语言的软件工程
  • 实现串口控制
  • 计算机网络 (31)运输层协议概念
  • JVM实战—11.OOM的原因和模拟以及案例
  • python代码实现了一个金融数据处理和分析的功能,主要围绕国债期货及相关指数数据展开
  • el-table表格合并某一列
  • 【集成学习】Bootstrap抽样