这些设计模式在现代C++中如何应用

设计模式在现代C++中的应用

设计模式是解决常见软件设计问题的可重用模板。在现代C++(C++11 及更高版本)中,新特性如智能指针、lambda 表达式、移动语义和 std::function 等,使设计模式的实现更简洁、安全和高效。下面我将逐步介绍几种常见设计模式在现代C++中的应用,包括代码示例。每个模式会先简要描述,然后解释现代C++特性如何优化实现,并提供实际代码。

1. 单例模式(Singleton)

单例模式确保一个类只有一个实例,并提供全局访问点。在现代C++中,使用智能指针(如 std::unique_ptr)可以避免内存泄漏,并确保线程安全(通过 C++11 的 std::call_once)。

现代C++实现关键点

  • 使用 std::unique_ptr 管理实例。
  • std::call_once 保证线程安全的初始化。
  • 禁用拷贝和移动构造函数。
cpp 复制代码
#include <memory>
#include <mutex>

class Singleton {
private:
    static std::unique_ptr<Singleton> instance;
    static std::once_flag flag;

    Singleton() {} // 私有构造函数
    Singleton(const Singleton&) = delete; // 禁用拷贝
    Singleton& operator=(const Singleton&) = delete; // 禁用赋值

public:
    static Singleton& getInstance() {
        std::call_once(flag, []() {
            instance = std::make_unique<Singleton>();
        });
        return *instance;
    }

    void doSomething() {
        // 示例方法
    }
};

std::unique_ptr<Singleton> Singleton::instance = nullptr;
std::once_flag Singleton::flag;

应用场景:全局配置管理或日志系统,确保只有一个实例共享资源。

2. 工厂模式(Factory)

工厂模式通过一个接口创建对象,而不指定具体类。现代C++中,lambda 表达式和 std::function 可以简化工厂的实现,避免复杂的继承层次。

现代C++实现关键点

  • 使用 std::function 存储创建函数。
  • 利用 lambda 表达式定义对象创建逻辑。
  • 结合 std::unordered_map 实现灵活的对象注册。
cpp 复制代码
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

class Product {
public:
    virtual ~Product() = default;
    virtual void use() = 0;
};

class ConcreteProductA : public Product {
public:
    void use() override {
        // 实现A
    }
};

class ConcreteProductB : public Product {
public:
    void use() override {
        // 实现B
    }
};

class Factory {
private:
    std::unordered_map<std::string, std::function<std::unique_ptr<Product>()>> creators;

public:
    void registerCreator(const std::string& type, std::function<std::unique_ptr<Product>()> creator) {
        creators[type] = creator;
    }

    std::unique_ptr<Product> create(const std::string& type) {
        if (auto it = creators.find(type); it != creators.end()) {
            return it->second(); // 调用lambda创建对象
        }
        return nullptr;
    }
};

// 使用示例
int main() {
    Factory factory;
    factory.registerCreator("A", []() -> std::unique_ptr<Product> { return std::make_unique<ConcreteProductA>(); });
    factory.registerCreator("B", []() -> std::unique_ptr<Product> { return std::make_unique<ConcreteProductB>(); });

    auto product = factory.create("A");
    if (product) {
        product->use();
    }
}

应用场景:插件系统或依赖注入,动态创建不同类型的对象。

3. 观察者模式(Observer)

观察者模式定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者自动更新。现代C++中,std::function 和 lambda 表达式替代了传统的接口继承,使代码更灵活。

现代C++实现关键点

  • 使用 std::function 存储观察者回调。
  • 结合 std::vector 管理多个观察者。
  • 利用 lambda 简化事件处理。
cpp 复制代码
#include <functional>
#include <vector>
#include <iostream>

class Subject {
private:
    std::vector<std::function<void(int)>> observers;

public:
    void attach(std::function<void(int)> observer) {
        observers.push_back(observer);
    }

    void notify(int data) {
        for (auto& observer : observers) {
            observer(data); // 调用回调函数
        }
    }
};

// 使用示例
int main() {
    Subject subject;

    // 添加观察者1:使用lambda
    subject.attach([](int data) {
        std::cout << "Observer 1: " << data << std::endl;
    });

    // 添加观察者2:使用lambda
    subject.attach([](int data) {
        std::cout << "Observer 2: " << data << std::endl;
    });

    subject.notify(42); // 触发更新
}

应用场景:GUI 事件处理或实时数据监控,解耦发布者和订阅者。

4. 策略模式(Strategy)

策略模式定义一系列算法,并使它们可互换。现代C++中,std::function 或模板参数可以替代虚函数,减少运行时开销并提升灵活性。

现代C++实现关键点

  • 使用 std::function 封装策略函数。
  • 或使用模板在编译时绑定策略。
  • 避免虚函数开销。
cpp 复制代码
#include <functional>
#include <iostream>

class Context {
private:
    std::function<int(int, int)> strategy; // 策略函数

public:
    void setStrategy(std::function<int(int, int)> strat) {
        strategy = strat;
    }

    int executeStrategy(int a, int b) {
        return strategy(a, b);
    }
};

// 使用示例
int main() {
    Context context;

    // 策略1:加法
    context.setStrategy([](int a, int b) -> int { return a + b; });
    std::cout << "10 + 5 = " << context.executeStrategy(10, 5) << std::endl;

    // 策略2:乘法
    context.setStrategy([](int a, int b) -> int { return a * b; });
    std::cout << "10 * 5 = " << context.executeStrategy(10, 5) << std::endl;
}

应用场景:排序算法或支付方式选择,动态切换行为。

总结

在现代C++中,设计模式的应用变得更简洁和安全:

  • 优势 :智能指针管理内存,避免泄漏;lambda 和 std::function 替代继承,减少样板代码;移动语义提升性能。
  • 建议 :优先使用现代特性(如 C++17 的 std::optional 或 C++20 的 concepts)来简化模式实现。实际开发中,结合具体需求选择模式,避免过度设计。
  • 注意事项 :确保线程安全(使用 std::mutex 或原子操作),并遵循 RAII 原则(Resource Acquisition Is Initialization)管理资源。

通过以上示例,您可以看到现代C++如何使设计模式更易于实现和维护。如果需要深入某个模式或更多模式(如装饰器或适配器),请提供进一步细节!

相关推荐
程序员老邢14 分钟前
【技术底稿 32】Nginx 经典大坑复盘:本机公网域名自环代理,导致接口返回首页 / 404 实战排障
java·运维·nginx·前后端分离·技术底稿·后端部署
该昵称用户已存在1 小时前
从成本中心到价值引擎:MyEMS 开源系统激活企业能源数据资产
java·后端·struts
想唱rap1 小时前
传输层协议TCP
linux·运维·服务器·网络·c++·tcp/ip
隐退山林1 小时前
JavaEE进阶:SpringBoot配置文件
java·spring boot·java-ee
阿维的博客日记1 小时前
求解深分页问题,last pk适合什么情况
java·mysql·深分页
瑶池酒剑仙1 小时前
C++类和对象完全指南:从封装继承多态到内存布局的面向对象宝典(雨夜论道)
c语言·开发语言·c++·visual studio
潇湘散客2 小时前
CAX软件插件化设计实现牛刀小试
c++·算法·图形学·opengl
Ricky_Theseus2 小时前
const 和 #define 的区别
c++
极客先躯2 小时前
高级java每日一道面试题-2025年12月09日-实战篇[Docker]-如何配置 Docker 的日志驱动?有哪些日志驱动可选?
java·docker·日志驱动的作用与配置层级·日志驱动全览与对比·日志驱动配置的要点·日志标签定制·容器与宿主机时间戳