单例模式的三种实现方法

来源:互联网 发布:网络客服有什么要求 编辑:程序博客网 时间:2024/05/16 00:52

在实际开发中,我们往往需要一个类只能被实例化一次,如果有多个对象的话,就会导致混乱情况发生。

优点

一、实例控制

单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。

二、灵活性

因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点

一、开销

虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。

二、可能的开发混淆

使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

三、对象生存期

不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。。

今天我们就来实现以下三个单例模式

1.懒汉式

class test{public:static test * gettest(){if (p == NULL)p = new test();return p;}private:test() {};static test*p;};

我们将类的构造函数声明为私有的,这样就不能通过构造函数来创建类对象,定义一个静态的gettest()函数来创建获取类资源,而这个函数不需要创建类对象,只需要通过类名访问即可。只有在第一次创建类对象时,资源进行了分配,其余时候不进行分配。这样就实现了一个类只有一个实例的要求。
缺点:存在内存泄露。new出来的东西始终没有释放。
2.饿汉式
class test {private:static test* p;test();class test2 {public:~test2(){if (test::p){delete test::p;}}};static test2 t;public:static test* gettest(){if (p == NULL){p = new test();return p;}}};
这里采用一种内嵌定义的方式,定义一个test2类,专门只做一件事,就是用来释放new出来的资源,当程序运行结束时,系统会自动析构所有的全局变量。会自动调用test2的析构函数,把p的资源释放。
饿汉式的特点是一开始就加载了,如果说懒汉式是时间换空间,那么饿汉式就是用空间换时间。
class test{private:test() {}public:test* gettest(){static testt;return &t;}}
这是一种饿汉式的方法,当类被创建好了之后,就已经存在一个静态的对象供系统使用,以后不会再改变。但是这也会存在一个问题,当我们使用下面的方法来调用的好时
test t1=test::gettest();就会出现一个类拷贝的问题,这就违背了单例模式的要求,因为编译器会给我们合成一个默认的构造函数,来支持类的拷贝。最后我们没办法,只能将类的拷贝构造函数和赋值运算符的重载声明为私有。于是有了下面这种代码。
class test{private:test() {}test(const test&t);test& operator=(const test&t);public:test* gettest(){static testt;return &t;}}






原创粉丝点击