欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单例模式:使用C++编写单例模式

程序员文章站 2022-07-14 09:03:50
...

概念:

单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。即一个类只能产生一个对象。

优点

  1. 实例控制
    单例模式会阻止其他对象实例化其自己的单例对象的副本,一个类只能创建一个对象,而创建的其他类也只是一个类通过指针或引用而来的,从而确保所有对象都访问唯一实例。
  2. 灵活性
    因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点

  1. 开销
    虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
  2. 可能的开发混淆
    使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
  3. 对象生存期
    不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。

创建单例类的步骤:

1,私有化该类的构造函数

2,通过new在本类中创建一个本类对象

3,提供一个共有的静态方法,将创建的对象返回

我学习中碰到的一些问题和思考:

  • 为什么类的创建时,需要用static

         类外想要调用类内函数的方法只有两种:第一种就是通过对象名.函数名;第二种就是定义为静态函数或者变量,然后通过类名::函数名直接调用。而此时创建的为单例模式,因此想要调用类内函数来创建对象,则只能将创建对象的函数定义为静态函数,然后通过类名::函数名的方法来创建对象。
       如果不用static,那你就必须生成对象才能调用,都可以直接生成对象了,哪就不能叫单例
       单例类因为不允许其他程序通过new来创建对象,所以只能将单例类中的方法定义为静态的(随类的加载而加载),静态方法不能访问非静态的成员,故只能将该类中的new的本质对象变为静态的

  • 为什么要定义为指针

        感觉就是为了检查单例类是否已经创建出了对象,如果指针为空,则没有创建对象;反之,则直接将该对象返回。

三种实现方法:

第一种:

最简单的一种创建单例模型的方法。

#include<iostream>
using namespace std;

class TA
{
private:
	int num;
	static TA* test;
	TA(){ num = 10; }
public:
	static TA * Create()
	{
		if (test == NULL)
		{
			test = new TA();
		}
		return test;
	}

	static void Delete()
	{
		if (test != NULL)
		{
			delete test;
			test = NULL;
		}
	}

	int sum()
	{
		return ++num;
	}
};

TA *TA::test = NULL;

int main()
{
	TA *test = TA::Create();
	cout << test->sum() << endl;

	TA *test1 = TA::Create();
	cout << test1->sum() << endl;

	TA::Delete();
	system("pause");
	return 0;
}

第二种:

在函数中创建出静态的对象,然后函数直接返回该对象的引用,此处没有写析构函数,因为一般这种单例类的对象都可能从头一直用到尾,因此程序结束的时候资源自然就会被释放。如果需要删除可以自己添加。

#include<iostream>
using namespace std;

class TA
{
private:
	int num;
	TA(){ num = 10; }
public:
	static TA *Create()
	{
		static TA test;
		return &test;
	}

	int sum()
	{
		return ++num;
	}
};

int main()
{
	TA *test = TA::Create();
	cout << test->sum() << endl;

	TA *test1 = TA::Create();
	cout << test1->sum() << endl;

	system("pause");
	return 0;
}

第三种:

看网上比较厉害的一种方法

#include <iostream>
using namespace std;

class Singleton
{
public:
	static Singleton *GetInstance()
	{
		return m_Instance;
	}

	int GetTest()
	{
		return m_Test;
	}

private:
	Singleton(){ m_Test = 10; }
	static Singleton *m_Instance;
	int m_Test;

	class GC
	{
	public:
		~GC()
		{
			if (m_Instance != NULL)
			{
				cout << "Here is the test" << endl;
				delete m_Instance;
				m_Instance = NULL;
			}
		}
	};
	static GC gc;
};

Singleton *Singleton::m_Instance = new Singleton();
Singleton::GC Singleton::gc;

int main(int argc, char *argv[])
{
	Singleton *singletonObj = Singleton::GetInstance();
	cout << singletonObj->GetTest() << endl;

	return 0;
}