07结构型设计模式——装饰器模式

一、装饰器模式简介

装饰器模式( Decorator Pattern)又称包装模式。通过一种面向客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。装饰器模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端可以有选择地、按顺序地使用装饰功能包装对象。

GoF一书对装饰器模式的介绍

二、装饰器模式的用处

装饰器模式允许在不改变对象结构的情况下,动态地给一个对象添加功能。这种模式通过创建一个装饰类来包装原有类的对象,从而增加新的功能。装饰器模式是面向对象编程中常用的一种设计模式,适用于需要在运行时动态地扩展对象功能的情况。

  1. 动态扩展功能

    • 装饰器模式允许在不修改原有类的情况下,通过添加装饰器类来动态地扩展对象的功能。这在需要根据不同的需求或条件来增加功能时非常有用。
  2. 增强类的灵活性

    • 通过组合装饰器对象,可以灵活地组合和扩展功能。这种组合的方式比子类化更为灵活,因为它允许在运行时决定具体的功能组合,而不需要修改现有类的代码。
  3. 避免类爆炸

    • 如果每种功能的组合都需要一个新的子类,那么子类数量将会大幅增加,导致类的管理变得困难。装饰器模式可以通过在运行时组合不同的装饰器对象来解决这个问题,从而避免了创建大量的子类。
  4. 遵循开闭原则

    • 装饰器模式遵循了开闭原则,即"对扩展开放,对修改关闭"。通过使用装饰器来增加功能,你可以在不修改原有类的情况下增加新的功能。
  5. 灵活的功能组合

    • 可以在运行时灵活地组合不同的装饰器,这使得功能组合非常灵活。你可以选择不同的装饰器来满足具体的需求,而不需要重新设计整个类层次结构。

三、装饰器模式的设计方法

基础类和装饰器:

  1. 定义基础类Cup:它代表一个基础的水杯。

  2. 定义装饰器基类CupDecorator:继承自Cup,用于装饰基本水杯。

  3. 定义具体装饰器:每个装饰器代表一种调料。

decorator.cpp

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>

// 水杯
class Cup {
public:
    virtual ~Cup() = default;
    virtual std::string getDescription() const {
        return "水杯放入";
    }
    virtual double cost() const {
        return 0.0; // 水杯的成本
    }
};

// 装饰器
class CupDecorator : public Cup {
public:
    CupDecorator(Cup* cup) : cup(cup) {}
    virtual ~CupDecorator() {
        delete cup;
    }
    std::string getDescription() const override {
        return cup->getDescription();
    }
    double cost() const override {
        return cup->cost();
    }

protected:
    Cup* cup;
};

// 调料
class CoffeePowderDecorator : public CupDecorator {
public:
    CoffeePowderDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Coffee Powder";
    }

    double cost() const override {
        return cup->cost() + 2.0; // 咖啡粉的附加费用
    }
};

class BrownSugarDecorator : public CupDecorator {
public:
    BrownSugarDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Brown Sugar";
    }

    double cost() const override {
        return cup->cost() + 1.0; // 红糖的附加费用
    }
};

class LemonSliceDecorator : public CupDecorator {
public:
    LemonSliceDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Lemon Slice";
    }

    double cost() const override {
        return cup->cost() + 0.5; // 柠檬片的附加费用
    }
};

class GojiBerriesDecorator : public CupDecorator {
public:
    GojiBerriesDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Goji Berries";
    }

    double cost() const override {
        return cup->cost() + 1.5; // 枸杞的附加费用
    }
};

class RedDateSlicesDecorator : public CupDecorator {
public:
    RedDateSlicesDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Red Date Slices";
    }

    double cost() const override {
        return cup->cost() + 2.0; // 红枣圈的附加费用
    }
};

class ChrysanthemumDecorator : public CupDecorator {
public:
    ChrysanthemumDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Chrysanthemum";
    }

    double cost() const override {
        return cup->cost() + 1.0; // 菊花的附加费用
    }
};

class YellowTeaDecorator : public CupDecorator {
public:
    YellowTeaDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Yellow Tea";
    }

    double cost() const override {
        return cup->cost() + 2.5; // 黄芽的附加费用
    }
};

class MilkDecorator : public CupDecorator {
public:
    MilkDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Milk";
    }

    double cost() const override {
        return cup->cost() + 2.5; // 牛奶的附加费用
    }
};

class WaterDecorator : public CupDecorator {
public:
    WaterDecorator(Cup* cup) : CupDecorator(cup) {}

    std::string getDescription() const override {
        return cup->getDescription() + ", Water";
    }

    double cost() const override {
        return cup->cost() + 0.0; // 水免费
    }
};

void printService(Cup* cup) {
    std::cout << "Description: " << cup->getDescription() << std::endl;
    std::cout << "Cost: $" << cup->cost() << std::endl;
}

// 纯水套餐
void servicePureWater() {
    Cup* myCup = new Cup();
    myCup = new WaterDecorator(myCup);
    printService(myCup);
    delete myCup;
}

// 咖啡套餐
void serviceCoffee() {
    Cup* myCup = new Cup();
    myCup = new WaterDecorator(myCup);
    myCup = new CoffeePowderDecorator(myCup);
    myCup = new BrownSugarDecorator(myCup);
    myCup = new MilkDecorator(myCup);
    printService(myCup);
    delete myCup;
}

// 饮料套餐
void serviceDrink() {
    Cup* myCup = new Cup();
    myCup = new WaterDecorator(myCup);
    myCup = new LemonSliceDecorator(myCup);
    myCup = new ChrysanthemumDecorator(myCup);
    printService(myCup);
    delete myCup;
}

// 养生套餐
void serviceHealth() {
    Cup* myCup = new Cup();
    myCup = new WaterDecorator(myCup);
    myCup = new YellowTeaDecorator(myCup);
    myCup = new GojiBerriesDecorator(myCup);
    myCup = new RedDateSlicesDecorator(myCup);
    printService(myCup);
    delete myCup;
}

int main() {
    servicePureWater();
    serviceCoffee();
    serviceDrink();
    serviceHealth();
    return 0;
}

运行效果

四、总结

通过装饰器模式(Decorator Pattern)可以灵活地组合各种调料,而不需要修改基础Cup类的代码去继承或者依赖什么的,只需要添加装饰器和要装饰的功能即可。装饰器模式的优点在于它提供了一种非常灵活的方式来扩展对象的功能。即通过装饰器动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。

相关推荐
hggngx548h17 小时前
有哪些C++20特性可以在Dev-C++中使用?
开发语言·c++·c++20
计科土狗17 小时前
算法基础入门第一章
c++·算法
9ilk18 小时前
【仿RabbitMQ的发布订阅式消息队列】 ---- 功能测试联调
linux·服务器·c++·分布式·学习·rabbitmq
北冥湖畔的燕雀18 小时前
std之list
数据结构·c++·list
Elias不吃糖18 小时前
eventfd 初认识Reactor/多线程服务器的关键唤醒机制
linux·服务器·c++·学习
南方的狮子先生19 小时前
【C++】C++文件读写
java·开发语言·数据结构·c++·算法·1024程序员节
玖剹19 小时前
二叉树递归题目(一)
c语言·c++·算法·leetcode
mjhcsp19 小时前
C++ 数组:基础与进阶全解析
开发语言·c++
量子炒饭大师19 小时前
【一天一个计算机知识】—— 【编程百度】翻译环境与运行环境
c语言·汇编·c++·gitee·机器翻译
今晚打老虎20 小时前
c++(斗罗大陆3)
开发语言·c++·斗罗大陆3