单例设计模式 ⭐
定义
单例模式是一种创建型设计模式,它的核心思想是保证一个类只有一个实例,并提供一个全局访问点来访问这个实例。
优点
1.全局控制:保证只有一个实例,这样就可以严格的控制客户怎样访问它以及何时访问它,简单的说就是对唯一实例的受控访问。
2. 节省资源:也正是因为只有一个实例存在,就避免多次创建了相同的对象,从而节省了系统资源,而且多个模块还可以通过单例实例共享数据。
3. 懒加载:单例模式可以实现懒加载,只有在需要时才进行实例化,这无疑会提高程序的性能。
基本要求(规则)
- 私有的构造函数:防止外部代码直接创建类的实例。
- 私有的静态实例变量:保存该类的唯一实例。
- 公有的静态方法:通过公有的静态方法来获取类的实例。
种类
饿汉模式
不管是否需要使用这个实例,直接先创建好实例,然后当需要使用的时候,直接调方法就可以使用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Singleton { private: static Singleton instance; private: Singleton() = default; ~Singleton() = default; Singleton(const Singleton&); Singleton& operator=(const Singleton&); public: static Singleton& getInstance() { return instance; } }
Singleton Singleton::instance;
|
懒汉模式
先不创建实例,当第一次被调用时,再创建实例,所以被称为懒汉式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| class lazySingleton { private: static lazySingleton* instance; private: lazySingleton() {} ~lazySingleton() {} lazySingleton(const lazySingleton&) = delete; lazySingleton& operator=(const lazySingleton&) = delete; public: static lazySingleton* getInstance() { if(instance == NULL) instance = new lazySingleton(); return instance; } }; lazySingleton* lazySingleton::instance = NULL;
class lazySingleton { private: lazySingleton() {} ~lazySingleton() {}
lazySingleton(const lazySingleton&) = delete; lazySingleton& operator=(const lazySingleton&) = delete; static lazySingleton* instance; static std::mutex mtx; public: static lazySingleton* getInstance() { std::lock_guard<std::mutex> lock(mtx); if (instance == nullptr) { instance = new lazySingleton(); } return instance; } };
lazySingleton* lazySingleton::instance = nullptr; std::mutex lazySingleton::mtx;
class lazySingleton { private: lazySingleton() = default; ~lazySingleton() = default; lazySingleton(const lazySingleton&) = delete; lazySingleton& operator=(const lazySingleton&) = delete; public: static lazySingleton& getInstance() { static lazySingleton instance; return instance; } };
class lazySingleton { public: static lazySingleton& getInstance() { static std::once_flag flag; std::call_once(flag, [&]() {instance.reset(new Singleton()); }); return *instance; }
private: static std::unique_ptr<lazySingleton> instance;
private: lazySingleton() = default; ~lazySingleton() = default; lazySingleton(const lazySingleton& other) = delete; lazySingleton& operator=(const lazySingleton&) = delete; }; std::unique_ptr<lazySingleton> lazySingleton::instance;
|
单例模式的应用场景
- 资源共享:当多个模块或系统需要共享某一资源时,可以使用单例模式确保该资源只被创建一次,避免重复创建和浪费资源。
- 控制资源访问:单例模式可以用于控制对特定资源的访问,例如数据库连接池、线程池等。
- 配置管理器:当整个应用程序需要共享一些配置信息时,可以使用单例模式将配置信息存储在单例类中,方便全局访问和管理。
- 日志记录器:单例模式可以用于创建一个全局的日志记录器,用于记录系统中的日志信息。
- 线程池:在多线程环境下,使用单例模式管理线程池,确保线程池只被创建一次,提高线程池的利用率。
- 缓存:单例模式可以用于实现缓存系统,确保缓存只有一个实例,避免数据不一致性和内存浪费。
应用场景举例:
- 网站计数器。
- 应用程序的日志应用。
Web
项目中的配置对象的读取。
- 数据库连接池。
- 多线程池。
使用场景总结:
- 频繁实例化然后又销毁的对象,使用单例模式可以提高性能。
- 经常使用的对象,但实例化时耗费时间或者资源多,如数据库连接池,使用单例模式,可以提高性能,降低资源损坏。
- 使用线程池之类的控制资源时,使用单例模式,可以方便资源之间的通信。