C++常用设计模式

前言:C++代码设计模式总共有23种,分为创建型模式、结构型模式和行为模式。本文针对常用的单例模式、简单工厂模式、工厂方法模式和抽象工厂模式进行介绍。

目录

一、为什么需要设计模式

二、单例模式

三、简单工厂模式

四、工厂方法模式

五、抽象工厂模式


一、为什么需要设计模式

C++ 需要设计模式,核心是解决其面向对象编程(OOP)的痛点、适配底层开发场景,同时弥补语言原生特性的不足。

设计模式为 C++ 提供了 "标准化的解决方案",让代码从 "随意写" 变成 "按规则写",提升了C++代码的工程化能力。

二、单例模式

1)定义 :保证一个类仅有一个实例,并对外提供一个全局访问点来访问这个实例

2)目的:解决 "对象重复创建" 问题,尤其适用于管理唯一的硬件资源(如 MCU 的时钟模块)

3)优缺点 :优点是 省资源;全局访问,使用方便。缺点是 无法扩展(违背"开闭原则"(可参考SOLID软件设计原则 解析-CSDN博客));耦合度高;全局访问,大大增加了出错的概率。

4)C++示例

饿汉式单例:

饿汉式在程序启动时(静态变量初始化阶段)就创建实例,天生线程安全,但可能会造成资源浪费(如果实例从未被使用)。

cpp 复制代码
#include <iostream>

class SingletonHungry {
private:
    // 私有构造函数:禁止外部创建对象
    SingletonHungry() {
        std::cout << "饿汉式单例构造" << std::endl;
    }

    // 禁用拷贝构造和赋值运算符:防止实例被复制
    SingletonHungry(const SingletonHungry&) = delete;
    SingletonHungry& operator=(const SingletonHungry&) = delete;

    // 静态成员变量:程序启动时初始化(全局区)
    static SingletonHungry instance;

public:
    // 全局访问点:返回唯一实例
    static SingletonHungry& getInstance() {
        return instance;
    }

    // 测试方法
    void doSomething() {
        std::cout << "饿汉式单例执行操作" << std::endl;
    }
};

// 静态成员变量初始化(类外定义)
SingletonHungry SingletonHungry::instance;

// 测试
int main() {
    // 获取实例并调用方法
    SingletonHungry& s1 = SingletonHungry::getInstance();
    SingletonHungry& s2 = SingletonHungry::getInstance();

    // 验证是否是同一个实例(地址相同)
    std::cout << "s1 地址: " << &s1 << std::endl;
    std::cout << "s2 地址: " << &s2 << std::endl;

    s1.doSomething();
    return 0;
}

懒汉式单例:

懒汉式是按需初始化 (第一次调用**getInstance()**时创建实例),C++11 及以上版本中,局部静态变量的初始化是线程安全的,这是最简洁且推荐的写法。

cpp 复制代码
#include <iostream>

class SingletonLazy {
private:
    // 私有构造函数
    SingletonLazy() {
        std::cout << "懒汉式单例构造" << std::endl;
    }

    // 禁用拷贝和赋值
    SingletonLazy(const SingletonLazy&) = delete;
    SingletonLazy& operator=(const SingletonLazy&) = delete;

public:
    // 全局访问点:局部静态变量(C++11 线程安全)
    static SingletonLazy& getInstance() {
        static SingletonLazy instance; // 第一次调用时初始化,仅初始化一次
        return instance;
    }

    // 测试方法
    void doSomething() {
        std::cout << "懒汉式单例执行操作" << std::endl;
    }

    // 析构函数(可选,用于验证析构时机)
    ~SingletonLazy() {
        std::cout << "懒汉式单例析构" << std::endl;
    }
};

// 测试
int main() {
    // 第一次调用:创建实例
    SingletonLazy& s1 = SingletonLazy::getInstance();
    // 第二次调用:返回已创建的实例
    SingletonLazy& s2 = SingletonLazy::getInstance();

    std::cout << "s1 地址: " << &s1 << std::endl;
    std::cout << "s2 地址: " << &s2 << std::endl;

    s1.doSomething();
    return 0;
}

三、简单工厂模式

1)定义 :一个工厂类根据传入的参数,动态创建不同的产品类实例(产品类需继承同一个抽象类 / 接口)。

2)目的 :将 "对象创建逻辑" 和 "业务逻辑" 分离,避免在业务代码中直接new不同的产品对象。

3)优缺点 :优点是 简化对象创建,产品创建与业务逻辑解耦。缺点是 工厂职责过重;如新增产品需修改代码,违背"开闭原则"(可参考SOLID软件设计原则 解析-CSDN博客)。

4)C++示例

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

// 抽象产品:图形
class Shape {
public:
    virtual void draw() const = 0;
    virtual ~Shape() = default;
};

// 具体产品:圆形/矩形
class Circle : public Shape {
public:
    void draw() const override { std::cout << "绘制圆形" << std::endl; }
};
class Rectangle : public Shape {
public:
    void draw() const override { std::cout << "绘制矩形" << std::endl; }
};

// 简单工厂:一个工厂创建所有产品
class ShapeFactory {
public:
    static std::unique_ptr<Shape> createShape(const std::string& type) {
        if (type == "circle") return std::make_unique<Circle>();
        if (type == "rectangle") return std::make_unique<Rectangle>();
        return nullptr;
    }
};

// 测试
int main_simple_factory() {
    auto circle = ShapeFactory::createShape("circle");
    if (circle) circle->draw(); // 输出:绘制圆形
    auto rect = ShapeFactory::createShape("rectangle");
    if (rect) rect->draw();     // 输出:绘制矩形
    return 0;
}

四、工厂方法模式

1)定义 :将 "产品创建" 延迟到具体工厂子类中,每个产品对应一个工厂子类,核心工厂类只定义创建产品的接口。

2)目的:解决简单工厂 "修改工厂代码" 的问题,新增产品只需新增工厂子类。

3)优缺点:优点是 符合 "开闭原则",便于维护。缺点是 逻辑较复杂;类数量翻倍(产品+工厂),占用更多内存。

4)C++示例

cpp 复制代码
#include <iostream>
#include <memory>

// 抽象产品:图形
class Shape {
public:
    virtual void draw() const = 0;
    virtual ~Shape() = default;
};

// 具体产品:圆形/矩形
class Circle : public Shape {
public:
    void draw() const override { std::cout << "绘制圆形" << std::endl; }
};
class Rectangle : public Shape {
public:
    void draw() const override { std::cout << "绘制矩形" << std::endl; }
};

// 抽象工厂:图形工厂
class ShapeFactory {
public:
    virtual std::unique_ptr<Shape> createShape() const = 0;
    virtual ~ShapeFactory() = default;
};

// 具体工厂:圆形工厂/矩形工厂
class CircleFactory : public ShapeFactory {
public:
    std::unique_ptr<Shape> createShape() const override {
        return std::make_unique<Circle>();
    }
};
class RectangleFactory : public ShapeFactory {
public:
    std::unique_ptr<Shape> createShape() const override {
        return std::make_unique<Rectangle>();
    }
};

// 测试
int main_factory_method() {
    std::unique_ptr<ShapeFactory> circleFactory = std::make_unique<CircleFactory>();
    auto circle = circleFactory->createShape();
    circle->draw(); // 输出:绘制圆形

    std::unique_ptr<ShapeFactory> rectFactory = std::make_unique<RectangleFactory>();
    auto rect = rectFactory->createShape();
    rect->draw();   // 输出:绘制矩形
    return 0;
}

五、抽象工厂模式

1)定义 :创建一系列相关 / 依赖 的**"产品族"**,而不指定具体类。

2)目的 :解决**"产品族"**的创建问题,保证同一产品族的组件能兼容使用。

3)优缺点:优点是 产品族内组件兼容;扩展性强。缺点是 最复杂的工厂模式,类数量多,占用内存大。

4)C++示例

cpp 复制代码
#include <iostream>
#include <memory>

// 抽象产品1:手机
class Phone {
public:
    virtual void call() const = 0;
    virtual ~Phone() = default;
};
// 具体产品1:小米手机/华为手机
class XiaomiPhone : public Phone {
public:
    void call() const override { std::cout << "用小米手机打电话" << std::endl; }
};
class HuaweiPhone : public Phone {
public:
    void call() const override { std::cout << "用华为手机打电话" << std::endl; }
};

// 抽象产品2:路由器
class Router {
public:
    virtual void connect() const = 0;
    virtual ~Router() = default;
};
// 具体产品2:小米路由器/华为路由器
class XiaomiRouter : public Router {
public:
    void connect() const override { std::cout << "连接小米路由器" << std::endl; }
};
class HuaweiRouter : public Router {
public:
    void connect() const override { std::cout << "连接华为路由器" << std::endl; }
};

// 抽象工厂:电子设备工厂(生产手机+路由器)
class ElectronicFactory {
public:
    virtual std::unique_ptr<Phone> createPhone() const = 0;
    virtual std::unique_ptr<Router> createRouter() const = 0;
    virtual ~ElectronicFactory() = default;
};

// 具体工厂:小米工厂/华为工厂(生产对应品牌的产品族)
class XiaomiFactory : public ElectronicFactory {
public:
    std::unique_ptr<Phone> createPhone() const override {
        return std::make_unique<XiaomiPhone>();
    }
    std::unique_ptr<Router> createRouter() const override {
        return std::make_unique<XiaomiRouter>();
    }
};
class HuaweiFactory : public ElectronicFactory {
public:
    std::unique_ptr<Phone> createPhone() const override {
        return std::make_unique<HuaweiPhone>();
    }
    std::unique_ptr<Router> createRouter() const override {
        return std::make_unique<HuaweiRouter>();
    }
};

// 测试
int main_abstract_factory() {
    // 小米工厂生产小米产品族
    std::unique_ptr<ElectronicFactory> xiaomiFactory = std::make_unique<XiaomiFactory>();
    auto xiaomiPhone = xiaomiFactory->createPhone();
    auto xiaomiRouter = xiaomiFactory->createRouter();
    xiaomiPhone->call();    // 输出:用小米手机打电话
    xiaomiRouter->connect();// 输出:连接小米路由器

    // 华为工厂生产华为产品族
    std::unique_ptr<ElectronicFactory> huaweiFactory = std::make_unique<HuaweiFactory>();
    auto huaweiPhone = huaweiFactory->createPhone();
    auto huaweiRouter = huaweiFactory->createRouter();
    huaweiPhone->call();    // 输出:用华为手机打电话
    huaweiRouter->connect();// 输出:连接华为路由器
    return 0;
}
相关推荐
__万波__2 小时前
二十三种设计模式(十四)--命令模式
java·设计模式·命令模式
鹿角片ljp2 小时前
力扣110.平衡二叉树-递归
数据结构·算法·leetcode
一起养小猫2 小时前
《Java数据结构与算法》第四篇(三)二叉树遍历详解_CSDN文章
java·开发语言·数据结构
im_AMBER2 小时前
Leetcode 80 统计一个数组中好对子的数目
数据结构·c++·笔记·学习·算法·leetcode
少许极端2 小时前
算法奇妙屋(十九)-子序列问题(动态规划)
java·数据结构·算法·动态规划·子序列问题
消失的旧时光-19432 小时前
从 Android 回调到 C 接口:函数指针 + void* self 的一次彻底理解
android·c语言·开发语言
尘诞辰2 小时前
【C语言】数据在内存中的储存
c语言·开发语言·数据结构·c++
无敌最俊朗@2 小时前
STL-关联容器(面试复习4)
开发语言·c++
无限进步_3 小时前
【C语言】栈(Stack)数据结构的实现与应用
c语言·开发语言·数据结构·c++·后端·visual studio