设计模式简记

98 阅读9分钟

1. 单例模式(Singleton Pattern)

单例模式确保一个类只有一个实例,并提供一个全局访问点。

#include <iostream>  
#include <mutex>  
  
class Singleton {  
private:  
    static Singleton* instance;  
    static std::mutex mtx;  
    Singleton() {}  
  
public:  
    static Singleton* getInstance()
    {  
        if (!instance)
        {  
            std::lock_guard<std::mutex> lock(mtx);  
            if (!instance)
            {  
                instance = new Singleton();  
            }  
        }  
        return instance;  
    }  
  
    void doSomething()
    {  
        std::cout << "Doing something..." << std::endl;  
    }  
  
    // 静态成员初始化  
    static std::once_flag onceFlag;  
    static void createInstance()
    {  
        instance = new Singleton();  
    }  
  
    // 使用C++11的std::call_once改进  
    static Singleton* getSafeInstance()
    {  
        std::call_once(onceFlag, createInstance);  
        return instance;  
    }  
};  
  
// 静态成员初始化  
Singleton* Singleton::instance = nullptr;  
std::mutex Singleton::mtx;  
std::once_flag Singleton::onceFlag;  
  
int main()
{ 
    Singleton* s1 = Singleton::getSafeInstance();  
    Singleton* s2 = Singleton::getSafeInstance();  
  
    if (s1 == s2)
    {  
        std::cout << "s1 and s2 are the same instance." << std::endl;  
    }  
  
    s1->doSomething();  
    return 0;  
}

1.1 懒汉式(线程不安全)

懒汉式单例在第一次使用时才创建实例,但这种简单的实现方式在多线程环境下是不安全的。

class Singleton
{  
private:  
    static Singleton* instance;  
    Singleton() {}  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
  
public:  
    static Singleton* getInstance()
    {  
        if (instance == nullptr)
        {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
  
    // 注意:需要提供一个删除实例的接口或在程序结束时自动回收资源  
    // 这里不展示,因为通常单例的生命周期与程序相同  
};  
  
Singleton* Singleton::instance = nullptr;

1.2 懒汉式(线程安全)

通过加锁(如使用std::mutex)来确保线程安全。

双重检查锁定的示例

#include <mutex>  
  
class Singleton
{  
private:  
    static Singleton* instance;  
    static std::mutex mtx;  
    Singleton() {}  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
  
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;

注意:上面的代码在C++11及之后的版本中可以编译通过,但如前所述,双重检查锁定在C++中通常不推荐使用,因为它依赖于编译器和硬件的内存模型。在C++11中,更推荐使用std::call_once结合局部静态变量来实现线程安全的延迟初始化。

使用std::call_once的推荐方式

#include <iostream>  
#include <mutex>  
  
class Singleton
{  
private:  
    static Singleton* instance;  
    static std::once_flag onceFlag;  
  
    Singleton() {}  
  
public:  
    static Singleton* getInstance()
    {  
        std::call_once(onceFlag, []()
        {  
            instance = new Singleton();  
        });  
        return instance;  
    }  
  
    // 析构函数需要为public或protected,且必须为delete,防止外部delete  
    ~Singleton() = delete;  
  
    // 禁用拷贝和赋值  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
};  
  
Singleton* Singleton::instance = nullptr;  
std::once_flag Singleton::onceFlag;  
  
int main()
{  
    Singleton* s1 = Singleton::getInstance();  
    Singleton* s2 = Singleton::getInstance();  
  
    // 验证s1和s2是否指向同一个实例  
    if (s1 == s2)
    {  
        std::cout << "s1 and s2 point to the same instance." << std::endl;  
    }  
  
    return 0;  
}

1.3 饿汉式

饿汉式单例在类加载时就完成了初始化,所以它是线程安全的。

class Singleton
{  
private:  
    static Singleton instance;  
    Singleton() {}  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
  
public:  
    static Singleton& getInstance()
    {  
        return instance;  
    }  
};  
  
Singleton Singleton::instance; // 在这里完成初始化

1.4 静态内部类(C++11及以后)

利用C++11的局部静态变量初始化特性,达到线程安全的懒加载效果。

class Singleton
{  
private:  
    Singleton() {}  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
  
    class SingletonHolder
    {  
    public:  
        static Singleton instance;  
    };  
  
public:  
    static Singleton& getInstance()
    {  
        return SingletonHolder::instance;  
    }  
  
private:  
    static Singleton& getInstanceHelper()
    {  
        static Singleton instance; // 局部静态变量,线程安全  
        return instance;  
    }  
  
    // 这里我们实际上没有使用SingletonHolder::instance,因为C++标准允许我们直接  
    // 在getInstance中返回一个局部静态变量,这样更简洁。但保留SingletonHolder的  
    // 形式展示了另一种思路,即利用类的作用域来隐藏实现细节。  
};  
  
// 注意:这里不需要显式定义SingletonHolder::instance,因为我们在getInstance中没有使用它  
// 如果使用SingletonHolder的方式,则需要这样定义:  
// Singleton Singleton::SingletonHolder::instance;  
  
// 直接使用  
// Singleton& singleton = Singleton::getInstance();

在实际应用中,可以根据具体需求和环境选择最适合的实现方式。例如,如果单例对象在程序启动时就必须存在,那么饿汉式可能是更好的选择;如果希望延迟加载以节省资源,则懒汉式或静态内部类可能更合适。

2. 工厂模式(Factory Pattern)

工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

#include <iostream>  
#include <memory>  
#include <string>  
  
// 产品接口  
class Product
{  
public:  
    virtual void use() = 0;  
    virtual ~Product() {}  
};  
  
// 具体产品A  
class ConcreteProductA : public Product
{  
public:  
    void use() override
    {  
        std::cout << "Using ConcreteProductA" << std::endl;  
    }  
};  
  
// 具体产品B  
class ConcreteProductB : public Product
{  
public:  
    void use() override
    {  
        std::cout << "Using ConcreteProductB" << std::endl;  
    }  
};  
  
// 工厂类  
class Factory {  
public:  
    static std::unique_ptr<Product> createProduct(const std::string& type)
    {  
        if (type == "A")
        {  
            return std::make_unique<ConcreteProductA>();  
        } 
        else if (type == "B")
        {  
            return std::make_unique<ConcreteProductB>();  
        }  
        return nullptr;  
    }  
};  
  
// 客户端代码  
int main()
{  
    auto productA = Factory::createProduct("A");  
    if (productA)
    {  
        productA->use();  
    }  
  
    auto productB = Factory::createProduct("B");  
    if (productB)
    {  
        productB->use();  
    }  
  
    return 0;  
}

在C++中,工厂设计模式主要用于创建对象,但无需指定具体要创建的对象类。工厂模式通过定义一个共同的接口来创建对象,但让子类决定要实例化的类是哪一个。这样做的好处是,增加新的具体类时,无需修改工厂类代码,只需要增加新的具体类并实现共同的接口。 工厂设计模式主要分为三种类型:简单工厂模式(Simple Factory Pattern)、工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)。

2.1 简单工厂模式(Simple Factory Pattern)

简单工厂模式不是GoF设计模式之一,但它是一种常用的设计模式。简单工厂模式通过定义一个工厂类,根据传入的参数决定创建哪个类的实例。

#include <iostream>  
#include <string>  
#include <memory>  
  
class Product
{  
public:  
    virtual void use() const = 0;  
    virtual ~Product() {}  
};  
  
class ConcreteProductA : public Product
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductA" << std::endl;  
    }  
};  
  
class ConcreteProductB : public Product
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductB" << std::endl;  
    }  
};  
  
class SimpleFactory
{  
public:  
    static std::unique_ptr<Product> createProduct(const std::string& type)
    {  
        if (type == "A")
        {  
            return std::make_unique<ConcreteProductA>();  
        } 
        else if (type == "B")
        {  
            return std::make_unique<ConcreteProductB>();  
        }  
        return nullptr;  
    }  
};  
  
int main() {  
    auto productA = SimpleFactory::createProduct("A");  
    if (productA) productA->use();  
  
    auto productB = SimpleFactory::createProduct("B");  
    if (productB) productB->use();  
  
    return 0;  
}

2.2 工厂方法模式(Factory Method Pattern)

工厂方法模式在工厂类中定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。

#include <iostream>  
#include <memory>  
  
class Product
{  
public:  
    virtual void use() const = 0;  
    virtual ~Product() {}  
};  
  
class ConcreteProductA : public Product
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductA" << std::endl;  
    }  
};  
  
class ConcreteProductB : public Product
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductB" << std::endl;  
    }  
};  
  
class Creator
{  
public:  
    virtual std::unique_ptr<Product> factoryMethod() const = 0;  
    virtual ~Creator() {}  
};  
  
class ConcreteCreatorA : public Creator
{  
public:  
    std::unique_ptr<Product> factoryMethod() const override
    {  
        return std::make_unique<ConcreteProductA>();  
    }  
};  
  
class ConcreteCreatorB : public Creator
{  
public:  
    std::unique_ptr<Product> factoryMethod() const override
    {  
        return std::make_unique<ConcreteProductB>();  
    }  
};  
  
int main() {  
    std::unique_ptr<Creator> creatorA = std::make_unique<ConcreteCreatorA>();  
    std::unique_ptr<Product> productA = creatorA->factoryMethod();  
    productA->use();  
  
    std::unique_ptr<Creator> creatorB = std::make_unique<ConcreteCreatorB>();  
    std::unique_ptr<Product> productB = creatorB->factoryMethod();  
    productB->use();  
  
    return 0;  
}

2.3 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

// 抽象工厂模式示例较为复杂,通常涉及多个产品族和产品等级结构  
// 这里仅展示概念框架  
  
class AbstractProductA
{  
public:  
    virtual void use() const = 0;  
    virtual ~AbstractProductA() {}  
};  
  
class AbstractProductB
{  
public:  
    virtual void anotherUse() const = 0;  
    virtual ~AbstractProductB() {}  
};  
  
class ConcreteProductA1 : public AbstractProductA
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductA1" << std::endl;  
    }  
};  
  
class ConcreteProductA2 : public AbstractProductA
{  
public:  
    void use() const override
    {  
        std::cout << "Using ConcreteProductA2" << std::endl;  
    }  
};  
  
class ConcreteProductB1 : public AbstractProductB
{  
public:  
    void anotherUse() const override
    {  
        std::cout << "Using ConcreteProductB1" << std::endl;  
    }  
};  
  
class ConcreteProductB2 : public AbstractProductB
{  
public:  
    void anotherUse() const override
    {  
        std::cout << "Using ConcreteProductB2" << std::endl;  
    }  
};  
  
class AbstractFactory
{  
public:  
    virtual std::unique_ptr<AbstractProductA> createProductA() const = 0;  
    virtual std::unique_ptr<AbstractProductB> createProductB() const = 0;  
    virtual ~AbstractFactory() {}  
};  
  
class ConcreteFactory1 : public AbstractFactory
{  
public:  
    std::unique_ptr<AbstractProductA> createProductA() const override
    {  
        return std::make_unique<ConcreteProductA1>();  
    }  
  
    std::unique_ptr<AbstractProductB> createProductB() const override
    {  
        return std::make_unique<ConcreteProductB1>();  
    }  
};  
  
// ConcreteFactory2 类似,但创建不同的产品  
// 主函数中,根据需要选择不同的工厂来创建产品

3. 观察者模式(Observer Pattern)

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

#include <iostream>  
#include <vector>  
#include <string>  
  
class Subject
{  
private:  
    std::vector<class Observer*> observers;  
    int state;  
  
public:  
    void attach(Observer* observer)
    {  
        observers.push_back(observer);  
    }  
  
    void detach(Observer* observer)
    {  
        auto it = std::find(observers.begin(), observers.end(), observer);  
        if (it != observers.end())
        {  
            observers.erase(it);  
        }  
    }  
  
    void notify(int newState)
    {  
        for (auto observer : observers)
        {  
            observer->update(newState);  
        }  
    }  
  
    void setState(int newState)
    {  
        state = newState;  
        notify(newState);  
    }  
};  
  
class Observer
{  
public:  
    virtual void update(int state) = 0;  
    virtual ~Observer() {}  
};  
  
class ConcreteObserver : public Observer
{  
private:  
    std::string name;  
  
public:  
    ConcreteObserver(std::string name) : name(name) {}  
  
    void update(int state) override
    {  
        std::cout << name << " notified, new state is " << state << std::endl;  
    }  
};  
  
int main()
{  
    Subject subject;  
    ConcreteObserver observer1("Observer 1");  
    ConcreteObserver observer2("Observer 2");  
  
    subject.attach(&observer1);  
    subject.attach(&observer2);  
  
    subject.setState(10);  
  
    subject.detach(&observer1);  
    subject.setState(20);  
  
    return 0;  
}

4. 策略模式(Strategy Pattern)

策略模式定义了一系列算法,并将每一种算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。策略模式属于行为型模式。

#include <iostream>  
#include <memory>  
  
// 定义一个策略接口  
class Strategy
{  
public:  
    virtual ~Strategy() {}  
    virtual void execute() = 0;  
};  
  
// 具体的策略A  
class ConcreteStrategyA : public Strategy
{  
public:  
    void execute() override
    {  
        std::cout << "Executing strategy A" << std::endl;  
    }  
};  
  
// 具体的策略B  
class ConcreteStrategyB : public Strategy
{  
public:  
    void execute() override
    {  
        std::cout << "Executing strategy B" << std::endl;  
    }  
};  
  
// 上下文类,维护对策略的引用  
class Context
{  
private:  
    std::unique_ptr<Strategy> strategy;  
  
public:  
    Context(std::unique_ptr<Strategy> strategy) : strategy(std::move(strategy)) {}  
  
    void setStrategy(std::unique_ptr<Strategy> strategy)
    {  
        this->strategy = std::move(strategy);  
    }  
  
    void executeStrategy()
    {  
        strategy->execute();  
    }  
};  
  
int main() {  
    Context context(std::make_unique<ConcreteStrategyA>());  
    context.executeStrategy();  // 输出:Executing strategy A  
  
    context.setStrategy(std::make_unique<ConcreteStrategyB>());  
    context.executeStrategy();  // 输出:Executing strategy B  
  
    return 0;  
}

5. 装饰器模式(Decorator Pattern)

装饰器模式动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。这种模式创建了一个包装对象,也就是装饰器,来包裹真实的对象。

#include <iostream>  
  
// 定义一个组件接口  
class Component
{  
public:  
    virtual ~Component() {}  
    virtual void operation() = 0;  
};  
  
// 具体的组件  
class ConcreteComponent : public Component
{  
public:  
    void operation() override
    {  
        std::cout << "ConcreteComponent's operation" << std::endl;  
    }  
};  
  
// 装饰器基类  
class Decorator : public Component
{  
protected:  
    Component* component;  
  
public:  
    Decorator(Component* component) : component(component) {}  
  
    void operation() override
    {  
        component->operation();  
    }  
};  
  
// 具体的装饰器  
class ConcreteDecoratorA : public Decorator
{  
public:  
    ConcreteDecoratorA(Component* component) : Decorator(component) {}  
  
    void operation() override
    {  
        Decorator::operation();  
        addedFunctionality();  
    }  
  
    void addedFunctionality()
    {  
        std::cout << "Added functionality in ConcreteDecoratorA" << std::endl;  
    }  
};  
  
int main() {  
    Component* component = new ConcreteComponent();  
  
    // 装饰者  
    Component* decorator = new ConcreteDecoratorA(component);  
  
    decorator->operation();  // 调用组件的operation,并添加新的功能  
  
    delete component;  
    delete decorator;  
  
    return 0;  
}

6. 适配器模式(Adapter Pattern)

适配器模式将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。

#include <iostream>  
  
// 目标接口  
class Target
{  
public:  
    virtual ~Target() {}  
    virtual void request() = 0;  
};  
  
// 适配的类  
class Adaptee
{  
public:  
    void specificRequest()
    {  
        std::cout << "Called specificRequest()" << std::endl;  
    }  
};  
  
// 适配器类  
class Adapter : public Target
{  
private:  
    Adaptee* adaptee;  
  
public:  
    Adapter(Adaptee* adaptee) : adaptee(adaptee) {}  
  
    void request() override
    {  
        adaptee->specificRequest();  
    }  
};  
  
int main() {  
    Adaptee* adaptee = new Adaptee();  
    Target* target = new Adapter(adaptee);  
  
    target->request();  // 输出:Called specificRequest()  
  
    delete adaptee;  
    delete target;  
  
    return 0;  
}