通过单例模式可以实现哪些目标?这个设计模式可以满足哪些需求?
单例模式的使用宗旨
确保一个类只有唯一的实例,并提供对该实例的全局访问。
使用宗旨包含两个方面的含义。
一方面,这个模式的任务是控制和管理其整个生命周期的唯一实例。
另一方面,提供了对该实例的全局访问,以便于应用程序中的所有其他对象都可以使用该实例。
实现单例模式
#pragma once
#ifndef SINGLETON_H_
#define SINGLETON_H
#include
#include
using namespace std;
class Singleton final
{
public:
static Singleton& getInstance() { //从C++11之后,在getInstance()中使用一个静态变量构造实例的过程,默认是线程安全的。
static Singleton theInstance{};
return theInstance;
}
int doSomething()
{
return 42;
}
static int getId()
{
if (id == -1)
{
cout << “recounter id” << endl;
id = 0;
}
else
{
cout << “add id” << endl;
id++;
}
return id;
}
public:
private:
Singleton()
{
cout << “construct a singleton!” << endl;
}
~Singleton()
{
cout << “construct a singleton!-----” << endl;
}
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(const Singleton&&) = delete;
static int id;
};
int Singleton::id = -1;
#endif // !SINGLETON_H_
#pragma once
#ifndef ANYSINLETONUSER_H
#define ANYSINLETONUSER_H
#include
#include
#include"Singleton.h"
using namespace std;
class AnySingletonUser
{
public:
AnySingletonUser(string name)
{
this->name = name;
}
int aMemberFunction();
string anotherMemberFunction();
int getSingletonId();
public:
string name;
};
int AnySingletonUser::aMemberFunction()
{
int result = Singleton::getInstance().doSomething();
return result;
}
string AnySingletonUser::anotherMemberFunction()
{
string resStr = to_string(Singleton::getInstance().doSomething());
return resStr;
}
int AnySingletonUser::getSingletonId()
{
return Singleton::getInstance().getId();
}
#endif // !ANYSINLETONUSER
#include"AnySingletonUser.cpp"
#include
int main()
{
AnySingletonUser anySingletonUser1(“the man”);
cout << anySingletonUser1.name<<":"<< anySingletonUser1.aMemberFunction() << anySingletonUser1.getSingletonId()<< endl;
AnySingletonUser anySingletonUser2("the woman");
cout << anySingletonUser2.name<<":"<< anySingletonUser2.anotherMemberFunction()<< anySingletonUser2.getSingletonId()<< endl;
}
单例模式的不足
由于单例的全局可见性和可访问性,其他类可以在任何地方使用单例。这就意味着在软件设计中,对单例对象的所有依赖都隐藏在了代码中。通过检查类的接口(即类的属性和方法)你无法看到这些依赖关系。
上面AnySingletoUser类的示例,仅代表了大型代码库中的数百个类,其中许多类在不同的地方都使用了单例。换句话说面向对象中单例的使用就像面向过程中全局变量的使用一样。你可以在任何地方使用这个对象,但是在类的接口中却看不到这种依赖,只能在代码实例中看到具体的应用。
所有的依赖关系在可重用性、可维护性和可测试性方面都有很大的缺点。所有使用Singleton的匿名客户端都与他紧密耦合在一起。
使用单例模式失去了利用多态替换实现的可能性。
单例模式的另一个缺点是,如果由于新的需求或需求变化而不得不更改,那么这种更改可能会触发所有依赖类的一系列更改。
在分布式系统中,很难保证一个类拥有唯一实例,这是体现在软件体系结构中一个常见的情况。想象一下微服务模式,一个复杂的软件系统是由许多小的、独立的和分布式的过程组成的。在这样的环境中,单例对象很难保证单实例化,并且由他们导致的紧密耦合也存在问题。