资料来源:设计模式精解-GoF 23 种设计模式解析附 C++
共23种经典设计模式,分类如下:
以及剑指offer中2.2.2的详细讲解。
单例模式的特点:
1、该类只有一个实例
2、该类在内部创建该实例
3、向整个系统公开这个实例接口
适用于多线程的四种编程方式:
第一种
将构造函数设为私有可以保证其他类不能从这个类派生或者创建类的实例
另外:析构函数私有化则是为了让某个类只能通过new来创建
class Singletion1
{
public:
static Singletion1* getInstance()
{
if(obj == NULL)
{
pthread_mutex_lock(&mutex);
if(obj == NULL)
{
obj = new Singleton1();
}
pthread_mutex_unlock(&mutex);
}
return obj;
}
private:
Singletion1(){}
static pthread_mutex_t mutex;
static Singletion1 obj;
}
这里解释一下为什么要要判断两次if(obj == NULL),如果没有第一次判断是可以的
static Singletion1* getInstance()
{
pthread_mutex_lock(&mutex);
if(obj == NULL)
{
obj = new Singleton1();
}
pthread_mutex_unlock(&mutex);
return obj;
}
只是每次用到这个实例的时候都会进入此函数,获得锁,判断,释放锁,而除第一次会进入这个函数外,其他的获得锁释放锁都会降低效率。
内层的判断是必不可少的:
static Singletion1* getInstance()
{
if(obj == NULL)
{
pthread_mutex_lock(&mutex);
obj = new Singleton1();
pthread_mutex_unlock(&mutex);
}
return obj;
}
比如在还没有创建实例的情况下,有两个线程A和B,Aif(obj == NULL)后进入条件获得锁执行new,Bif(obj == NULL)后进入条件等待锁(阻塞),等A创建完毕后释放锁,此时B获得锁执行new操作,注意注意,B执行new之前A已经创建好一个实例了,所以已经出错。
第二种(C#)
class Singletion2
{
public:
static Singletion2 Instance
{
get
{
return obj;
}
}
private:
Singletion2(){}
static Singletion2 obj = new Singletion2();
}
这种方法在调用接口时创建的对象,而是第一次用到Singletion2时就创建好了。
另外:sealed 修饰符表示密封用于类时,表示该类不能再被继承
第三种
class Singletion3
{
public:
static Singletion3 Instance
{
get
{
return obj;
}
}
private:
Singletion3(){}
static Singletion2 obj = new Singletion3();
}
第四种
class Singletion3
{
Singletion3() {}
public static Singletion3 Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested() {}
internal static readonly Singletion3 instance = new Singletion3();
}
}
第四种可在调用接口时再调用构造函数。
另外,internal 修饰符使类、接口或成员仅在当前包中可见。 当前包之外的代码不能访问 internal 成员。
应用场景
单例模式应用的场景一般发现在以下条件下:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等
(2)控制资源的情况下,方便资源之间的互相通信。
具体的没用过也不清楚,目前遇到的问题好像并没有需要单例,以后补充。