【C++】—— 装饰器模式

简介: 【C++】—— 装饰器模式



(一)什么是装饰器模式

装饰模式(Decorator Pattern),也被称为包装模式,是一种通过对客户端透明的方式来扩展对象功能的设计模式,它提供了一种替代继承关系的方案。装饰模式通过将要添加的附加功能放在独立的类中,并让这个类包含要装饰的对象,实现了在运行时动态地给对象添加功能的能力。

在装饰模式中,抽象构件定义了对象的接口,具体构件是被装饰的对象,装饰者持有一个构件对象的引用,并定义与抽象构件一致的接口。装饰者可以在调用构建对象的方法前后添加额外的行为,从而扩展对象的功能。

通过使用装饰模式,我们可以灵活地在运行时动态地给对象添加功能,而无需改变原有类的结构。客户端可以按照需要选择、按顺序使用不同的装饰者来包装对象,从而达到组合各种功能的目的。这种方式实现了功能的扩展和复用,同时也避免了使用继承带来的静态特性和多个子类的维护问题。


(二)为什么要使用装饰器模式

  1. 装饰模式可以动态的给一个对象添加一 些额外的职责。
  2. 就增加功能来说,此模式比生成子类更为灵活,通过子类继承的方式,但是如果后续继续增加功能的话,便要继续继承现有的类,如此就会使继承的层次越来越深,不利与代码的维护和可读性。
  3. 故最好的方式便是通过装饰者模式来完成。

(三)装饰器模式的实现步奏

  • 提供一个抽象组件类:抽象被装饰者的行为
  • 提供一个或多个具体组件类:被装饰者的行为具体实现
  • 提供一个抽象装饰器类:抽象组件指针与抽象组件一致接口
  • 提供一个具体的装饰器类:为具体组件附加责任


(四)代码示例

场景

  • 对于一些职场人士在出席一些重要场合的时候,大部分都是西装革履的。因此,我在这里就模拟男士穿衣的场景

首先,定义一个抽象基类Boy代表男生;

class Boy {
public:
    virtual void wearClothes() = 0;
};

接下来,创建具体的男生类;

class ConcreteBoy : public Boy {
public:
    void wearClothes() override {
        cout << "首先穿上打底衫" << endl;
    }
};

然后,定义装饰器基类;

class Decorator : public Boy {
protected:
    Boy* boy;
public:
    Decorator(Boy* b) : boy(b) {}
    virtual void wearClothes() override {
        if (boy != nullptr) {
            boy->wearClothes();
        }
    }
};

接着,创建具体的装饰器类;

//穿西装
class JacketDecorator : public Decorator {
public:
    JacketDecorator(Boy* b) : Decorator(b) {}
    void wearClothes() override {
        Decorator::wearClothes();
        cout << "紧接着穿上西服" << endl;
    }
};
//打领带
class TieDecorator : public Decorator {
public:
    TieDecorator(Boy* b) : Decorator(b) {}
    void wearClothes() override {
        Decorator::wearClothes();
        cout << "最后再打领带" << endl;
    }
};

最后,在主函数中使用这些类来展示男生穿衣服的场景;

int main() {
    Boy* boy = new TieDecorator(new JacketDecorator(new ConcreteBoy()));
    boy ->wearClothes();
    delete boy ;
    return 0;
}

(五)装饰器模式优缺点

优点

  1. 灵活性:装饰器模式允许动态地给对象添加功能,而且可以根据需要多次进行装饰,从而实现各种组合方式,使得功能扩展变得非常灵活。
  2. 开闭原则:装饰器模式符合开闭原则,可以在不修改现有代码的情况下,增加新的功能。

缺点

  1. 复杂性:装饰器模式引入了许多小的对象和类,可能会导致系统中对象数量的增加,从而增加系统的复杂性。
  2. 容易出错:由于装饰器模式允许灵活地组合对象,因此在设计时需要特别小心,以避免出现过度复杂或混乱的装饰器组合,导致难以理解和维护的问题。

总体来说,装饰器模式是一种非常灵活的设计模式,能够有效地扩展对象的功能,同时也需要在设计时注意控制复杂性,避免出现过度装饰的情况。

相关文章
|
7月前
|
设计模式 uml C++
C++中的装饰器模式:灵活地扩展功能
C++中的装饰器模式:灵活地扩展功能
103 0
|
设计模式 C++
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
|
设计模式 C++
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
设计模式(基于C/C++实现)<五>装饰器模式
|
24天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
38 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
83 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
80 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
87 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
31 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
32 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
26 1