设计模式—单例模式
1、学习框架
2、为什么需要单例模式?
在我们日常的工作中经常需要在应用程序中保持一个唯一的实例,如:IO处理,数据库操作等,由于这些对象都要占用重要的系统资源,所以我们必须限制这些实例的创建或始终使用一个公共的实例,这就是我所分享的设计模式—单例模式(Singleton)
单例模式需要确保某个类中只有一个实例,而且自行实例化并向整个系统提供这个实例。
2.1、单例模式常见的应用场景
| 场景 | 具体使用 |
|---|---|
| 网站 | 计数器 |
| web应用 | 配置管理器 |
| 应用程序 | 日志管理系统 |
| 数据库 | 连接池 |
| 多线程 | 线程池 |
| 资源性应用 | 内存池 |
| 操作系统 | 文件系统或打印机 |
2.2、单例类的特点
- 单例类只能有一个实例
- 单例类必须自己创建自己的唯一实例
- 单例类必须给所有其它对象提供这一实例
3、什么是单例模式?
3.1、单例模式的概念
单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
3.2、单例模式结构图
单例模式是几个创建模式中最对立的一个,它的主要特点不是根据用户程序调用生成一个新的实例,而是控制某个类型的实例唯一性,我们可以通过看如下图,知道该模式所包含的角色只有一个,就是Singleton,它拥有一个私有构造函数,这确保用户无法通过new直接实例它。除此之外,该模式中包含一个静态私有成员变量和静态公有方法,该方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。
单例模式结构图
4、如何实现单例模式?
这里主要介绍饿汉式实现和懒汉式实现,这两种实现方式的特点如下所示:
| 实现方式 | 优点 | 特点 |
|---|---|---|
| 饿汉式实现 | 加载进程时,静态创建单例对象,线程安全 | 无论使用与否,总是需要创建 |
| 懒汉式实现 | 用则创建,不用不创建,什么时间用什么事件创建 | 首次访问时动态创建单例对象,在多线程应用中,存在线程不安全的问题 |
4.1、饿汉式实现方式
将单例类的唯一对象实例,实现为其静态成员变量
class Singleton
{
private:
//私有的构造函数
Singleton();
//私有的拷贝函数
Singleton(const Singleton &);
public:
static Singleton &getInstance()
{
return instance;
}
private:
//创建静态成员变量
static Singleton instance;
};
4.2、懒汉式实现方式
直到第一次使用,才创建单例类的唯一对象实例
class Singleton
{
private:
//私有的构造函数
Singleton();
//私有的拷贝函数
Singleton(const Singleton &);
public:
static Singleton &getInstance()
{
//首次instance为NULL时,执行new
if (instance == NULL) {
instance = new Singleton;
}
return *instance;
}
private:
//创建静态成员变量
static Singleton *instance = NULL;
};
4.3、考虑线程安全的单例模式
借助互斥锁防止单例对象在不同线程中被重复创建
//创建互斥锁
pthread_mutex_t Singleton::mutex = PTHREAD_MUTEX_INITIALIZER;
class Singleton
{
private:
//私有的构造函数
Singleton();
//私有的拷贝函数
Singleton(const Singleton &);
public:
static Singleton &getInstance()
{
//首次instance为NULL时,执行new
//添加互斥锁,防止单例对象在不同的线程中被重复创建
pthread_mutex_lock(&mutex);
if (instance == NULL) {
instance = new Singleton;
}
pthread_mutex_unlock(&mutex);
return *instance;
}
private:
//创建静态成员变量
static Singleton *instance = NULL;
};
//优化:
//因为在第一次进行instance判断时,加锁可能起作用,但是在以后instance不为空时,可能造成性能的损失,故进行优化。
public:
static Singleton &getInstance()
{
//首次instance为NULL时,执行new
//仅在单利对象未创建时加锁,提高效率
if (!instance) {
pthread_mutex_lock(&mutex);
if (instance == NULL) {//这个if判断不可省略,防止在其他线程中在创建实例
instance = new Singleton;
}
pthread_mutex_unlock(&mutex);
}
return *instance;
}
5、什么是线程安全
如果代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,那就是线程安全。
2637

被折叠的 条评论
为什么被折叠?



