设计模式(十五)--装饰模式

目录

装饰模式的关键概念

装饰模式的优点

装饰模式的缺点

例子:咖啡饮品

步骤 1:定义Component接口

步骤 2:创建装饰结构

输出结果

说明

优点

总结


装饰模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时保持原有的结构不变。装饰模式通过动态地将责任附加到对象上来实现这一点。这种类型的动态关联是替代使用继承的灵活替代方案。

装饰模式的关键概念

  1. Component(组件)接口:定义了被装饰对象的基本行为。
  2. Concrete Component(具体组件):实现了Component接口,是被装饰的对象。
  3. Decorator(装饰器)类:也是Component接口的实现者,它可以装饰具体的组件,并在原有的行为上添加新的行为。
  4. Concrete Decorator(具体装饰器)类:继承自Decorator,提供了具体的装饰功能。

装饰模式的优点

  • 灵活性:可以在运行时动态地添加职责。
  • 扩展性:可以通过组合不同的装饰器来获得不同的效果。
  • 透明性:装饰器和具体组件都实现了同一个接口,使得客户端可以一致地处理它们。

装饰模式的缺点

  • 过度使用:可能导致类的数量增加,使得系统变得复杂。
  • 调试难度:装饰器模式可能导致对象创建的逻辑变得复杂,使得调试更加困难。

例子:咖啡饮品

假设我们正在设计一个咖啡店的菜单系统,其中包含基础的咖啡饮品和各种额外的配料。我们希望能够在运行时动态地添加配料,而不改变原有饮品的基本结构。

步骤 1:定义Component接口
 

c

深色版本

1#include <iostream>
2#include <string>
3
4class Beverage {
5public:
6    virtual ~Beverage() {}
7    virtual std::string getDescription() const = 0;
8    virtual double cost() const = 0;
9};
10
11class Espresso : public Beverage {
12public:
13    std::string getDescription() const override {
14        return "Espresso";
15    }
16    double cost() const override {
17        return 1.99;
18    }
19};
20
21class HouseBlend : public Beverage {
22public:
23    std::string getDescription() const override {
24        return "House Blend Coffee";
25    }
26    double cost() const override {
27        return 0.89;
28    }
29};
30
31class Decorator : public Beverage {
32protected:
33    Beverage *beverage;
34public:
35    Decorator(Beverage *beverage) : beverage(beverage) {}
36    std::string getDescription() const override {
37        return beverage->getDescription();
38    }
39    double cost() const override {
40        return beverage->cost();
41    }
42};
43
44class Mocha : public Decorator {
45public:
46    Mocha(Beverage *beverage) : Decorator(beverage) {}
47    std::string getDescription() const override {
48        return Decorator::getDescription() + ", Mocha";
49    }
50    double cost() const override {
51        return Decorator::cost() + 0.20;
52    }
53};
54
55class Soy : public Decorator {
56public:
57    Soy(Beverage *beverage) : Decorator(beverage) {}
58    std::string getDescription() const override {
59        return Decorator::getDescription() + ", Soy";
60    }
61    double cost() const override {
62        return Decorator::cost() + 0.15;
63    }
64};
步骤 2:创建装饰结构
 

c

深色版本

1int main() {
2    // 创建基础饮品
3    Beverage *houseBlend = new HouseBlend();
4    std::cout << houseBlend->getDescription() << " $" << houseBlend->cost() << std::endl;
5
6    // 添加配料
7    Beverage *houseBlendWithSoy = new Soy(houseBlend);
8    std::cout << houseBlendWithSoy->getDescription() << " $" << houseBlendWithSoy->cost() << std::endl;
9
10    // 添加更多配料
11    Beverage *houseBlendWithMochaAndSoy = new Mocha(houseBlendWithSoy);
12    std::cout << houseBlendWithMochaAndSoy->getDescription() << " $" << houseBlendWithMochaAndSoy->cost() << std::endl;
13
14    // 创建另一种饮品
15    Beverage *espresso = new Espresso();
16    std::cout << espresso->getDescription() << " $" << espresso->cost() << std::endl;
17
18    // 添加配料
19    Beverage *espressoWithMocha = new Mocha(espresso);
20    std::cout << espressoWithMocha->getDescription() << " $" << espressoWithMocha->cost() << std::endl;
21
22    // 清理
23    delete houseBlendWithMochaAndSoy;
24    delete houseBlendWithSoy;
25    delete houseBlend;
26    delete espressoWithMocha;
27    delete espresso;
28
29    return 0;
30}

输出结果

 

plaintext

深色版本

1House Blend Coffee $0.89
2House Blend Coffee, Soy $1.04
3House Blend Coffee, Soy, Mocha $1.24
4Espresso $1.99
5Espresso, Mocha $2.19

说明

在这个例子中:

  • Beverage 是抽象基类,定义了饮品的基本行为。
  • Espresso 和 HouseBlend 是具体组件,分别代表不同的基础饮品。
  • Decorator 是抽象装饰器,继承自 Beverage,并提供了一个指向具体组件的引用。
  • Mocha 和 Soy 是具体装饰器,它们继承自 Decorator,并在原有的饮品上添加新的配料。

优点

  • 灵活性:可以在运行时动态地添加配料,而不需要改变原有饮品的结构。
  • 透明性:所有的饮品(基础饮品和装饰后的饮品)都实现了相同的接口,使得客户端可以一致地处理它们。

总结

装饰模式通过动态地添加职责来扩展对象的功能,而无需通过继承来改变原有的结构。这种模式非常适合需要在运行时灵活地添加功能的场景。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值