bigtalk.jpg
第21章 有些类也需计划生育——单例模式
概念
单例模式保证一个类仅有一个对象实例,并且提供一个访问它的全局访问点。
其实全局对象貌似可以实现只有一个实例,但是却不能保证没有人再次创建这样的实例。最稳妥的方法就是将实例化放到类本身中进行,让类本身负责保证其对象的唯一性。
实现
实现单实例类Singleton, 包括:
- 一个它本身类型的instance成员,此处就是该类唯一的一个实例,只初始化一次存于此,便于后续判断。
- 一个私有的构造函数使得外部无法创建对象
- 一个GetInstance公共接口,用来获取该实例(这里有一个判断分支,若没有实例化的时候调用私有构造函数实例化该类并将对象存于instance)。
注:GetInstance是静态方法。
单实例模式类图:
20_singleton.png
单实例模式客户端使用:
20_singleton_use.png
客户端使用的方式就是: Singleton.GetInstance();
, 除了控制唯一实例,还对唯一的实例进行受控访问。
其它
多线程中的锁定:
- 在
GetInstance()
中,判断是否单实例前加锁,可以避免多个线程同时进入该函数的单实例判断,并同时创建对象。 - 双重锁定减少资源浪费:每次调用
GetInstance()
判断前都要加锁会浪费资源,加锁之前也进行单实例判断,这样若无两个进程同时进入判断就不用加锁了。 - 双重锁定形式:
if(conxx) {lock(xxx); if(conxx) {new()}};
两次if(conxx)
, 第一次是为了减少锁的次数,第二次是防止多个进程同时创建。
注:这是在使用时创建单实例对象,叫做懒汉式单实例。
静态初始化:
直接在类中用静态成员的方式进行单实例创建: class Singleton{ static Singleton instance=new Singleton();...}
这样就不用双重锁定了,
这种借助语言运行环境实现单实例不用双重锁定的方式,叫做饿汉式单实例。