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()等待所有线程执行完毕。
相关推荐
南东山人4 小时前
一文说清:C和C++混合编程
c语言·c++
Ysjt | 深6 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__6 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
Microsoft Word7 小时前
c++基础语法
开发语言·c++·算法
一只小小汤圆7 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz7 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
嘿BRE8 小时前
【C++】几个基本容器的模拟实现(string,vector,list,stack,queue,priority_queue)
c++
ö Constancy8 小时前
c++ 笔记
开发语言·c++
fengbizhe8 小时前
笔试-笔记2
c++·笔记