第十八章、设计模式

设计模式(Design Pattern)是软件工程中被多数人总结出来的一套软件设计经验。它是一套成熟的方案,可以在某些应用场合直接拿来借鉴。

常见的设计模式有:单例模式、工厂模式、观察者模式等。

1. 单例模式

单例模式(Singleton Pattern)用于在确保一个类在整个程序运行期间,有且仅有一个实例(对象)存在,并提供一个全局访问点来获取它的设计模式。

使用 C++ 语言实现单例模式有两种实现方法:

  1. 饿汉式(提前初始化)
  2. 懒汉式

1. 饿汉式

饿汉式指在类加载时(main 调用前)就立即创建好实例(对象),之后则禁止再创建新实例的实现方式。

饿汉式的优点是写法简单、线程安全(无需加锁);缺点是即使你暂时没用它,它也会占用内存。

示例:

使用饿汉式方式创建 Singleton 类型的单例。

// filename: singleton1.cpp
class Singleton {
    public:
        // 获取单例的接口函数
        static Singleton &getInstance() {
            return s_instance;
        }
    public:
        void do_things(void) {
            // 单例做事情的成员函数
        }
    private:
        Singleton() = default; // 私有全部构造函数
        // 删除拷贝构造、拷贝赋值、移动构造、移动赋值
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        Singleton(const Singleton&&) = delete;  // C++11或之后版本
        Singleton& operator=(const Singleton&&) = delete;  // C++11或之后版本
    private:
        static Singleton s_instance;
};

// 创建单例
Singleton Singleton::s_instance;

int main(int argc, char * argv[]) {
    // 用法
    Singleton &s(Singleton::getInstance());
    s.do_things();

    return 0;
}

2. 懒汉式

懒汉式指在程序第一次调用 getInstance() 来获取实例(对象)时才创建实例(对象),之后则禁止再创建新实例的实现方式。

懒汉式的优点启动时不占用内存,只有在需要时才动态创建实例(对象);缺点是如果多线程同时调用 getInstance() 来获取实例,可能会同时创建多个对象,需要加锁来对创建对象的临界区进行保护。好有一个缺点是需要手动释放单例对象。

示例:

使用懒汉式 方式创建 Singleton 类型的单例。

// filename: singleton2.cpp
#include <mutex>

class Singleton {
    public:
        // 获取单例的接口函数
        static Singleton &getInstance() {
            if (nullptr == instance) {
                std::lock_guard<std::mutex> lock(mtx);
                if (instance == nullptr) {      // 第二次检查
                    instance = new Singleton();
                }
            }
            return *instance;
        }
    public:
        void do_things(void) {
            // 单例做事情的成员函数
        }
    private:
        Singleton() = default; // 私有全部构造函数
        // 删除拷贝构造、拷贝赋值、移动构造、移动赋值
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        Singleton(const Singleton&&) = delete;  // C++11或之后版本
        Singleton& operator=(const Singleton&&) = delete;  // C++11或之后版本
    private:
        static Singleton *instance;
        static std::mutex mtx;
};

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

int main(int argc, char * argv[]) {
    // 用法
    Singleton &s(Singleton::getInstance());
    s.do_things();

    return 0;
}