【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. 容易出错:由于装饰器模式允许灵活地组合对象,因此在设计时需要特别小心,以避免出现过度复杂或混乱的装饰器组合,导致难以理解和维护的问题。

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

相关文章
|
设计模式 uml C++
C++中的装饰器模式:灵活地扩展功能
C++中的装饰器模式:灵活地扩展功能
231 0
|
设计模式 C++
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
118 0
|
设计模式 C++
[学习][笔记]设计模式(基于C/C++实现)<五>装饰器模式
设计模式(基于C/C++实现)<五>装饰器模式
184 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
10月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
414 12
|
8月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
220 0
|
8月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
353 0
|
11月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
212 16
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
11月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。