C++ 设计模式

1、工厂模式

1.1、简单工厂模式(Simple Factory Pattern)

简单工厂模式并不是GoF(Gang of Four)提出的设计模式之一,但它是工厂模式的一种简单形式,通常用来创建同一层次的对象。在简单工厂模式中,一个工厂类根据传入的参数,动态决定应该创建哪一个产品类的实例。

cpp 复制代码
// 简单工厂示例
class Product {
public:
    virtual void use() = 0;
    virtual ~Product() {}
};

class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using ConcreteProductA" << std::endl;
    }
};

class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using ConcreteProductB" << std::endl;
    }
};

class SimpleFactory {
public:
    Product* createProduct(char type) {
        switch (type) {
            case 'A':
                return new ConcreteProductA();
            case 'B':
                return new ConcreteProductB();
            default:
                return nullptr;
        }
    }
};

int main() {
    SimpleFactory factory;
    Product* productA = factory.createProduct('A');
    if (productA)
        productA->use();

    Product* productB = factory.createProduct('B');
    if (productB)
        productB->use();

    delete productA;
    delete productB;

    return 0;
}

1.2、工厂方法模式(Factory Method Pattern)

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。换句话说,工厂方法模式将对象的实例化延迟到子类。

cpp 复制代码
// 工厂方法模式示例
class Product {
public:
    virtual void use() = 0;
    virtual ~Product() {}
};

class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using ConcreteProductA" << std::endl;
    }
};

class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using ConcreteProductB" << std::endl;
    }
};

class Factory {
public:
    virtual Product* createProduct() = 0;
    virtual ~Factory() {}
};

class ConcreteFactoryA : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductA();
    }
};

class ConcreteFactoryB : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductB();
    }
};

int main() {
    Factory* factoryA = new ConcreteFactoryA();
    Product* productA = factoryA->createProduct();
    productA->use();

    Factory* factoryB = new ConcreteFactoryB();
    Product* productB = factoryB->createProduct();
    productB->use();

    delete productA;
    delete productB;
    delete factoryA;
    delete factoryB;

    return 0;
}

1.3、抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供了一个创建一系列相关或依赖对象的接口,而无需指定它们具体的类。抽象工厂模式通常用于需要一组相关产品对象的情况。

cpp 复制代码
// 抽象工厂模式示例
class AbstractProductA {
public:
    virtual void use() = 0;
    virtual ~AbstractProductA() {}
};

class ConcreteProductA1 : public AbstractProductA {
public:
    void use() override {
        std::cout << "Using ConcreteProductA1" << std::endl;
    }
};

class ConcreteProductA2 : public AbstractProductA {
public:
    void use() override {
        std::cout << "Using ConcreteProductA2" << std::endl;
    }
};

class AbstractProductB {
public:
    virtual void consume() = 0;
    virtual ~AbstractProductB() {}
};

class ConcreteProductB1 : public AbstractProductB {
public:
    void consume() override {
        std::cout << "Consuming ConcreteProductB1" << std::endl;
    }
};

class ConcreteProductB2 : public AbstractProductB {
public:
    void consume() override {
        std::cout << "Consuming ConcreteProductB2" << std::endl;
    }
};

class AbstractFactory {
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
    virtual ~AbstractFactory() {}
};

class ConcreteFactory1 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA1();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB1();
    }
};

class ConcreteFactory2 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA2();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB2();
    }
};

int main() {
    AbstractFactory* factory1 = new ConcreteFactory1();
    AbstractProductA* productA1 = factory1->createProductA();
    AbstractProductB* productB1 = factory1->createProductB();

    productA1->use();
    productB1->consume();

    delete productA1;
    delete productB1;
    delete factory1;

    AbstractFactory* factory2 = new ConcreteFactory2();
    AbstractProductA* productA2 = factory2->createProductA();
    AbstractProductB* productB2 = factory2->createProductB();

    productA2->use();
    productB2->consume();

    delete productA2;
    delete productB2;
    delete factory2;

    return 0;
}

2、单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点
2.1、 饿汉式(Eager Initialization) 在程序运行前就创建好单例对象。

cpp 复制代码
class Singleton {
private:
    static Singleton* instance;
    
    // 私有构造函数,防止外部创建实例
    Singleton() {}
    
public:
    // 全局访问点,返回单例实例
    static Singleton* getInstance() {
        return instance;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = new Singleton();

2.2、懒汉式(Lazy Initialization) 在首次使用时创建单例对象。

cpp 复制代码
class Singleton {
private:
    static Singleton* instance;
    
    // 私有构造函数,防止外部创建实例
    Singleton() {}
    
public:
    // 全局访问点,返回单例实例
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
};

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

2.3、 静态成员变量方式 使用静态成员变量保证只有一个实例,并通过静态成员函数返回该实例。

cpp 复制代码
class Singleton {
private:
    // 私有静态成员变量
    static Singleton instance;
    
    // 私有构造函数,防止外部创建实例
    Singleton() {}
    
public:
    // 全局访问点,返回单例实例
    static Singleton& getInstance() {
        return instance;
    }
};

// 初始化静态成员变量
Singleton Singleton::instance;

2.4、 C++11及以上标准的线程安全实现 利用局部静态变量和std::mutex保证线程安全。

cpp 复制代码
#include <mutex>

class Singleton {
private:
    // 私有静态成员变量
    static Singleton* instance;
    static std::mutex mtx;
    
    // 私有构造函数,防止外部创建实例
    Singleton() {}
    
public:
    // 全局访问点,返回单例实例
    static Singleton* getInstance() {
        std::lock_guard<std::mutex> lock(mtx);
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

注意事项

单例模式在多线程环境下需要特别注意实现的线程安全性。

单例模式可能会对代码的测试性产生影响,因为单例状态可能会在测试 中影响其他测试用例。

在使用单例模式时,应该考虑是否真的需要全局唯一的实例,以及它是否会导致代码的耦合性过高等问题。

3、观察者模式

观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听并且被通知一个主题对象的状态变化。

在观察者模式中,通常有以下几个角色:

Subject(主题):

维护一组观察者对象,提供注册和删除观察者对象的接口。
当主题状态变化时,通知所有注册的观察者对象。

Observer(观察者):

定义一个更新接口,用于主题状态变化时接收通知和更新自身状态。

ConcreteSubject(具体主题):

具体的主题实现,继承或实现Subject接口,并实现相关业务逻辑。

ConcreteObserver(具体观察者):

具体的观察者实现,实现Observer接口中的更新方法,以便在主题状态变化时执行相应操作。

Subject 类

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

class Observer; // 前置声明

class Subject {
public:
    virtual ~Subject() {}
    virtual void attach(Observer* observer) {
        observers.push_back(observer);
    }
    virtual void detach(Observer* observer) {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }
    virtual void notify() {
        for (auto observer : observers) {
            observer->update();
        }
    }
    virtual void setState(int state) {
        this->state = state;
        notify();
    }
    virtual int getState() const {
        return state;
    }

private:
    std::vector<Observer*> observers;
    int state;
};

Observer 类

cpp 复制代码
class Observer {
public:
    virtual ~Observer() {}
    virtual void update() = 0;
protected:
    Observer() {}
};

ConcreteSubject 类

cpp 复制代码
class ConcreteObserver : public Observer {
public:
    ConcreteObserver(Subject* subject) : subject(subject) {
        subject->attach(this);
    }
    ~ConcreteObserver() {
        subject->detach(this);
    }
    void update() override {
        std::cout << "Observer updated. New state: " << subject->getState() << std::endl;
    }
private:
    Subject* subject;
};

实例:

cpp 复制代码
int main() {
    ConcreteSubject subject;
    ConcreteObserver observer1(&subject);
    ConcreteObserver observer2(&subject);

    subject.setState(1);
    subject.setState(2);

    return 0;
}

观察者模式允许主题对象和观察者对象之间解耦,使得可以动态地添加或删除观察者对象。在C++中,可以利用虚函数和指针来实现接口的多态性,从而达到通知和更新观察者的目的。

4、生产者-消费者模式

生产者消费者模式(Producer-Consumer Pattern)是一种常见的并发设计模式,适用于多线程编程环境下解决生产者和消费者之间的数据交换和同步问题。在C++中,可以使用标准库提供的线程支持和同步机制来实现这一模式。

关键组成部分:
共享缓冲区:

生产者和消费者之间通常需要一个共享的缓冲区来存储生产的数据,以便消费者可以从中取出数据。
在C++中,可以使用标准库的数据结构如std::queue作为共享缓冲区。

互斥锁(Mutex):

互斥锁用于保护共享资源(如缓冲区),防止多个线程同时访问和修改数据而造成数据竞争。
在C++中,可以使用std::mutex来实现互斥锁。

条件变量(Condition Variable):

条件变量用于线程间的通信,允许一个线程在满足特定条件时等待,而另一个线程在条件变为真时通知等待的线程继续执行。
在C++中,std::condition_variable结合std::unique_lock<std::mutex>用于实现条件变量。

示例代码:

以下是一个简单的生产者消费者模式的实现,假设生产者产生整数并放入缓冲区,消费者从缓冲区取出整数进行消费。

cpp 复制代码
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

std::queue<int> buffer;  // 共享缓冲区
const int max_buffer_size = 10;
std::mutex mtx;  // 互斥锁
std::condition_variable buffer_not_full, buffer_not_empty;  // 条件变量

void producer(int id) {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        buffer_not_full.wait(lock, [] { return buffer.size() < max_buffer_size; });

        buffer.push(i);
        std::cout << "Producer " << id << " produced: " << i << std::endl;

        buffer_not_empty.notify_all();
    }
}

void consumer(int id) {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        buffer_not_empty.wait(lock, [] { return !buffer.empty(); });

        int val = buffer.front();
        buffer.pop();
        std::cout << "Consumer " << id << " consumed: " << val << std::endl;

        buffer_not_full.notify_all();
    }
}

int main() {
    std::thread producer1(producer, 1);
    std::thread producer2(producer, 2);
    std::thread consumer1(consumer, 1);
    std::thread consumer2(consumer, 2);

    producer1.join();
    producer2.join();
    consumer1.join();
    consumer2.join();

    return 0;
}
bash 复制代码
生产者函数 (producer):生产者不断产生整数并放入缓冲区,使用buffer_not_full条件变量来控制缓冲区未满的情况。
消费者函数 (consumer):消费者从缓冲区取出整数并进行消费,使用buffer_not_empty条件变量来控制缓冲区非空的情况。
主函数 (main):创建了两个生产者线程和两个消费者线程,并通过join()等待所有线程执行完毕。
相关推荐
JSU_曾是此间年少15 分钟前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋1 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧1 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
lulu_gh_yu2 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??3 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者3 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者4 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>4 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可5 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite