我尝试使用singleton模式只连接到数据库一次,下面是我的实现。
它能保证m_connector.connect();
只被调用一次吗?
使用singleton是最好的解决方案吗?
class ConnectionManager
{
public:
static ConnectionManager& getManager()
{
static ConnectionManager manager;
return manager;
}
void reconnect();
Connection getConnection();
private:
ConnectionManager():m_connector("port")
{
m_connector.connect();
};
ConnectionManager(ConnectionManager const&);
void operator=(ConnectionManager const&);
Connector m_connector;
};
它能保证
m_connector.connect();
只运行一次吗?
没有。
在这种实现(也称为Scott Meyer的Singleton)的情况下,唯一可以保证的事实是ConnectionManager
的构造函数只被调用一次。
static ConnectionManager& getManager()
{
static ConnectionManager manager;
return manager;
}
它将在第一次调用ConnectionManager::getManager();
时立即调用。
构造函数依次调用m_connector.connect()
ConnectionManager():m_connector("port")
{
m_connector.connect();
};
不能保证
m_connector.connect();
不会从代码的任何其他部分调用。的声明
void reconnect();
甚至以某种方式暗示了这一点。
但是,这一切都在你的控制之下。
如果构造函数是唯一一个调用m_connector.connect();
的函数,并且您担心线程安全,那么您不应该这样做。根据当前标准,它保证是线程安全的。
使用singleton是最好的解决方案吗?
可能不会。没有什么会阻碍你以后修改你的决定,并决定你实际上需要更多的ConnectionManager
实例。
代码中任何其他将使用ConnectionManager::getManager();
的部分都与该单例类紧密耦合,如果应该使代码更通用,那么将很难重构代码。
这种硬编码的数据库连接
ConnectionManager():m_connector("port")
// ^^^^^^
极大地缩小了应用程序的可伸缩性。
我个人会把它作为一个类,使用适当的构造函数参数来创建连接,并实现一个公共(抽象)接口,可以通过工厂函数或其他一些专门用于实例创建的创造性设计模式来访问,而不是其他。