单例模式的特点:
1、单例类只能有一个实例。
2、单例类必须自行创建自己的唯一的实例。
3、单例类必须自行向所有其他对象提供这个实例。
多例模式的特点:(多例模式实际就是单例模式的自然推广)
1、多例类可以有多个实例。
2、多例类必须自行创建,管理自己的实例,并向外界提供自己的实例。
单例就是为了防止反复去New某个类型的对象,有两种写法:
懒汉式:
public class Single{
private Single(){
}
private static instance = new Single(); //需要在类外部初始化:Singleton* Singleton::instance = NULL;
public static Single getInstance(){
return instance;
}
}
此方式容易导致并发。下面的恶汉式,加上了事务锁,可以防止并发
public class Single{
private static Single instance;
private Single(){
}
public synchronized static Single getInstance(){
if(instance == null)
instance = new Single();
return instance;
}
}
需要使用此对象时,只要调取得实例的那个方法即可
Single single = Single.getInstance();
讨论1:
singleton是不用new的。如果用了new,在什么地方去delete它呢?singleton原理的基础是局部static变量。
-
C/C++ code
-
class Singleton
{
private :
static Singleton * instance;
Singleton()
{
}
public :
static Singleton * GetInstance()
{
static Singleton singleton;
return & singleton
}
};
这种局部static变量只有在函数被调用的第一次才被创建,随着程序的结束而结束。
《Modern C++ Design》这本书里面对Singleton有详细的实现,包括相互依赖的Singleton实现。
讨论2:
你这个方法实现singleton不太好,会有多线程同步问题。
比如说一开始Singleton::instance为空。然后有线程A和线程B同时访问Singleton::GetInstance()。
有
意思的是当任务A执行if (NULL ==
instance)这句时,刚判断好instance确实为空想调用new,或者时间可以再放款到正在执行new操作,但是还没有返回;要命的是调度器由
于某些原因一下子剥夺了线程A的执行又去执行线程B了。线程B顺利地创建了一个instance实例,然后在某一时刻被调度器剥夺,再次执行线程A。
OK,此时线程A从刚才的混沌中继续执行它的new
Singleton()的操作,这样线程A所创建出来的就是另一个实例了。此时Singleton宣告破灭。
因此,能够迎合多线程,乃至多处理的单件处理可以用以下方式:
-
C/C++ code
-
class Singleton
{
private :
static Singleton instance;
Singleton( void )
{
}
public :
static Singleton & GetInstance()
{
return instance;
}
};
Singleton Singleton::instance;
由于以上代码中,Singleton::instance在程序加载后由初始化程序建立,因此对于应用程序不会有多线程困扰。如果是在多处理器或多核处理器环境下还要注意Singleton的成员函数中的一些同步。
讨论3:
static data + static member function !=singleton,
不容易销毁,那本书叫做 不死的凤凰