当前位置: 首页 > article >正文

工程实践中常见的几种设计模式解析及 C++ 实现

工程实践中常见的几种设计模式解析及 C++ 实现

在软件工程中,设计模式是一种通用的解决方案,用于解决常见问题和优化代码结构。它们通过提供一种规范化的编程思想,帮助开发者写出更高效、可维护和可扩展的代码。本文将介绍几种在工程实践中常见的设计模式,包括其实现原理、使用场景以及注意事项,并结合 C++ 语言进行实现。


1. 单例模式 (Singleton Pattern)

实现原理

单例模式确保一个类只有一个实例,并提供全局访问点。其核心思想是通过控制构造函数和复制操作符,使得类只能生成一个对象实例。

关键点:
  • 隐藏构造函数(将构造函数设为私有)。
  • 提供一个静态方法用于获取唯一实例。
  • 使用懒汉式或饿汉式实现线程安全的单例模式。

使用场景

  • 当需要全局只有一个实例时,例如配置管理、日志记录等。
  • 需要避免大量重复对象创建的情况。

注意事项

  • 单例模式可能会隐藏类之间的依赖关系,导致代码难以维护。
  • 线程安全性需要额外处理(如双重检查锁定)。
  • 在某些场景下,单例模式可能导致性能问题或内存泄漏。
C++ 实现
class Singleton {
private:
    static Singleton* instance;
    Singleton() = default;  // 隐藏构造函数
    ~Singleton() = default; // 隐藏析构函数

public:
    // 静态方法获取实例(线程安全)
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }

    // 删除复制操作符,防止复制
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    void doSomething() {
        // 业务逻辑
    }
};

// 静态变量初始化为 nullptr
Singleton* Singleton::instance = nullptr;

int main() {
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();

    if (s1 == s2) { // 比较两个指针是否相同
        // 输出:两者指向同一个实例
    }

    return 0;
}

2. 工厂模式 (Factory Pattern)

实现原理

工厂模式通过提供一个接口,用于创建对象,而无需显式指定具体类。这提高了代码的灵活性和可扩展性。

关键点:
  • 定义一个抽象产品类(Product)。
  • 提供一个工厂类(Factory),通过其方法创建具体的子类实例。
  • 工厂模式分为简单工厂模式和抽象工厂模式。

使用场景

  • 需要根据不同的条件动态选择具体实现时。
  • 避免代码直接依赖于具体实现类,提高系统的灵活性。

注意事项

  • 工厂类可能会变得复杂,尤其是在支持多种产品的情况下。
  • 增加新的产品类需要同时修改工厂类,这可能违反“开闭原则”。
C++ 实现
// 抽象产品类
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 {
public:
    virtual ~Factory() = default;
    virtual std::unique_ptr<Product> createProduct() = 0;
};

// 具体工厂类 A
class ConcreteFactoryA : public Factory {
public:
    std::unique_ptr<Product> createProduct() override {
        return std::make_unique<ConcreteProductA>();
    }
};

// 具体工厂类 B
class ConcreteFactoryB : public Factory {
public:
    std::unique_ptr<Product> createProduct() override {
        return std::make_unique<ConcreteProductB>();
    }
};

int main() {
    // 使用工厂创建产品
    Factory* factory = new ConcreteFactoryA();
    auto product = factory->createProduct();
    product->use();

    delete factory;
    return 0;
}

3. 观察者模式 (Observer Pattern)

实现原理

观察者模式定义了一种一对多的依赖关系,当一个对象(主题)的状态发生变化时,所有依赖它的对象(观察者)都会收到通知并自动更新。

关键点:
  • 定义一个主题类(Subject),包含状态和注册/注销观察者的接口。
  • 观察者类(Observer)通过继承或实现接口,提供一个更新方法。
  • 主题类维护一个观察者列表,并在状态变化时通知所有观察者。

使用场景

  • 系统中存在一对多的依赖关系时。
  • 需要动态地添加或删除观察者。

注意事项

  • 观察者模式可能会导致循环依赖问题。
  • 观察者和主题之间的耦合可能会影响代码的可维护性。
C++ 实现
#include <vector>
#include <memory>

class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(int value) = 0;
};

class Subject {
private:
    int state_;
    std::vector<std::shared_ptr<Observer>> observers_;

public:
    void attach(std::shared_ptr<Observer> observer) {
        observers_.push_back(observer);
    }

    void detach(std::shared_ptr<Observer> observer) {
        // 实现观察者的移除逻辑
    }

    int getState() const {
        return state_;
    }

    void setState(int value) {
        if (state_ != value) {
            state_ = value;
            notify();
        }
    }

private:
    void notify() {
        for (auto& observer : observers_) {
            observer->update(state_);
        }
    }
};

class ConcreteObserver : public Observer {
public:
    void update(int value) override {
        // 处理状态变化
    }
};

int main() {
    std::shared_ptr<Subject> subject = std::make_shared<Subject>();
    std::shared_ptr<ConcreteObserver> observer1 = std::make_shared<ConcreteObserver>();
    std::shared_ptr<ConcreteObserver> observer2 = std::make_shared<ConcreteObserver>();

    subject->attach(observer1);
    subject->attach(observer2);

    subject->setState(10); // 所有观察者都会收到更新

    return 0;
}

4. 策略模式 (Strategy Pattern)

实现原理

策略模式定义了一系列算法,并将它们封装起来,使它们可以互换。上下文类通过接口调用具体策略类的方法。

关键点:
  • 定义一个策略接口(Strategy),包含算法的声明。
  • 具体策略类(Concrete Strategy)实现策略接口。
  • 上下文类(Context)维护一个策略对象,并根据需要切换策略。

使用场景

  • 需要动态选择不同算法时。
  • 系统中存在多个相似但具体的算法,且希望它们可以互换使用。

注意事项

  • 增加新的具体策略类可能会影响上下文的代码复杂性。
  • 必须确保所有策略接口的一致性。
C++ 实现
class Strategy {
public:
    virtual ~Strategy() = default;
    virtual int calculate(int a, int b) = 0;
};

// 具体策略类 A:加法
class AddStrategy : public Strategy {
public:
    int calculate(int a, int b) override {
        return a + b;
    }
};

// 具体策略类 B:乘法
class MultiplyStrategy : public Strategy {
public:
    int calculate(int a, int b) override {
        return a * b;
    }
};

// 上下文类
class Context {
private:
    std::shared_ptr<Strategy> strategy_;

public:
    Context(std::shared_ptr<Strategy> strategy) : strategy_(strategy) {}

    void setStrategy(std::shared_ptr<Strategy> strategy) {
        strategy_ = strategy;
    }

    int execute(int a, int b) {
        return strategy_->calculate(a, b);
    }
};

int main() {
    std::shared_ptr<Context> context = std::make_shared<Context>(std::make_shared<AddStrategy>());

    // 使用加法策略
    int result1 = context->execute(3, 5); // 8

    // 切换到乘法策略
    context->setStrategy(std::make_shared<MultiplyStrategy>());
    int result2 = context->execute(3, 5); // 15

    return 0;
}

总结

以上四种设计模式(单例模式、工厂模式、观察者模式和策略模式)是工程实践中最常用的设计模式之一。每种模式都有其适用的场景和注意事项,合理使用它们可以显著提升代码的质量和系统的可维护性。

在实际开发中,我们需要根据具体需求选择合适的设计模式,并结合语言特性和框架进行实现。同时,也要注意避免过度设计,以免增加不必要的复杂性。


http://www.kler.cn/a/563846.html

相关文章:

  • vue3使用iframe全屏展示pdf效果
  • Day11,Hot100(贪心算法)
  • android跳转到相册选择图片
  • 基于 Java 和 FFmpeg 的视频压缩与剪辑功能实现
  • Python客服机器人
  • auto.js例子之WebView多页面浏览器
  • 算法-二叉树篇10-二叉树的所有路径
  • 爬虫案例-爬取某猫的电影数据
  • 大模型最新面试题系列:深度学习基础(一)
  • Redis 运维实战指南:常用命令解析与场景化操作
  • 程序代码篇---C/C++中的变量存储位置
  • Day 50 卡玛笔记
  • PnP——根据3D与2d图片估计相机运动
  • NCYpred:一个具有注意力机制的双向Lstm网络,用于Y Rna和短的非编码Rna分类
  • 11. 断藕重连术 - 反转链表(迭代与递归)
  • [数据结构]栈问题之括号匹配
  • Ubuntu配置ROS2环境 使用串口通信
  • SSL和CA什么关系?
  • centos22.04 dpkg -l 输出状态标识含义
  • DMA 定制固件教程:小白跟做即得单人固件,超详细纯喂饭教程,100% 成功秘籍!FPGA仿真1:1、中断逻辑和TLP核心都在。