- 单例模式:指程序运行过程中只能存在一个该类的对象。此时,程序维护该一个对象。
保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
模式中的角色:
单例:在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;
为了防止在外部对其实例化,将其构造函数设计为私有;
在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。
优点:
(1) 单例模式提供了对唯一实例的受控访问。
(2) 节约系统资源。由于在系统内存中只存在一个对象。
缺点:
(1) 扩展略难。单例模式中没有抽象层。
(2) 单例类的职责过重。
适用场景:
(1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。
(2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
三个要点:
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
- 为了不让其他类生产该对象,因此,单例模式下的构造函数是私有成员函数
单例模式的使用步骤:
a) 构造函数私有化。
b) 提供一个全局的静态方法(全局访问点)来获取单例对象。
c) 在类中定义一个静态指针,指向本类的变量的静态变量指针。
- 单例模式的两种实现方式:
//单例模式分为懒汉模式和饿汉模式
//懒汉模式:只有调用对象的创建函数时,才创建该对象的实例
//饿汉模式:在编译时就创建该对象的实例
//懒汉式
class Singleton_lazy
{
public:
static Singleton_lazy* getInstance()
{
//直接在第一次调用的时候创建该实例
if (pSingleton == NULL)
return new Singleton_lazy;
return pSingleton;
}
private:
Singleton_lazy() { cout << "我在main函数里产生" << endl; }
private:
static Singleton_lazy* pSingleton;
};
//类外初始化
Singleton_lazy* Singleton_lazy::pSingleton = NULL;
//饿汉式
class Singleton_hungry
{
public:
static Singleton_hungry* getInstance()
{
return pSingleton;
}
private:
Singleton_hungry() { cout << "我在main函数前产生" << endl; }
private:
static Singleton_hungry* pSingleton;
};
//类外初始化创建对象
Singleton_hungry* Singleton_hungry::pSingleton = new Singleton_hungry;
- 单例模式对象的释放:一般来说,单例模式只有一个对象,不会消耗多少内存,不用考虑在程序执行过程中释放对象。程序执行结束后,会自动释放内存。如果一定要释放,在单例类中嵌套定义一个类,该类中只有一个析构函数,用于释放单例对象内存。
- 单例模式 + 多线程:由于单例模式全局唯一,因此需要对该对象加锁。
- 懒汉式单例模式 + 多线程:由于不确定程序执行代码的时间和顺序,因此,如果都执行到判空语句,多个线程都想创建对象,造成线程不安全
- 饿汉式 + 多线程:由于在编译时创建的对象,是线程安全的。