如果连接对象在连接失败时无法正常工作,那么如果所有其他方法始终不执行任何操作或抛出异常,则该对象不存在意义。因为这个原因,我会在构造函数中执行连接,如果此方法失败,则抛出异常(从std::exception
派生)将失败。
然而,你是对的,类的客户端可能需要知道构造函数可能阻塞或失败。出于这个原因,我可能会选择使构造函数保持私有状态,并使用静态工厂方法(名为constructor idiom),以便客户端必须进行明确的MakeConnection
调用。
确定没有连接是否致命或是否可以处理离线模式仍然是客户的责任。在前一种情况下,它可以通过价值拥有连接,并让任何连接失败传播给其客户;在后者中,它可以通过指针来拥有对象,最好是“聪明”的。在后一种情况下,它可能会选择尝试在其构造函数中构建自己的连接,或者可能会将其延迟直到需要。
E.g. (警告:代码全部未经测试)
class Connection
{
Connection(); // Actually make the connection, may throw
// ...
public:
static Connection MakeConnection() { return Connection(); }
// ...
};
这是需要工作连接的类。
class MustHaveConnection
{
public:
// You can't create a MustHaveConnection if `MakeConnection` fails
MustHaveConnection()
: _connection(Connection::MakeConnection())
{
}
private:
Connection _connection;
};
这是一个没有一个可以工作的类。
class OptionalConnection
{
public:
// You can create a OptionalConnectionif `MakeConnection` fails
// 'offline' mode can be determined by whether _connection is NULL
OptionalConnection()
{
try
{
_connection.reset(new Connection(Connection::MakeConnection()));
}
catch (const std::exception&)
{
// Failure *is* an option, it would be better to capture a more
// specific exception if possible.
}
}
OptionalConnection(const OptionalConnection&);
OptionalConnection& operator=(const OptionalConnection&);
private:
std::auto_ptr<Connection> _connection;
}
最后是一个按需创建一个,并向调用者传播异常。
class OnDemandConnection
{
public:
OnDemandConnection()
{
}
OnDemandConnection(const OnDemandConnection&);
OnDemandConnection& operator=(const OnDemandConnection&);
// Propgates exceptions to caller
void UseConnection()
{
if (_connection.get() == NULL)
_connection.reset(new Connection(Connection::MakeConnection()));
// do something with _connection
}
private:
std::auto_ptr<Connection> _connection;
}
当然阻塞构造函数也有例外,例如基于RAII的锁。当然,文档和适当的命名非常重要。 – 2010-01-27 00:19:41
+1通过在单独的连接方法中执行阻止操作,您可以使用'cancel'方法取消该操作。 – 2010-01-27 02:26:22