13

通过使用单例,只能创建它的一个实例。我们是否需要销毁该实例?

我有一个单例 DBManager,它管理 JDBC 连接和查询操作。通过调用它的静态 newInstance 方法,我可以得到它的实例,然后我做一些查询。最后,我想关闭数据库连接,我调用另一个静态方法 close 来关闭 JDBC 连接。

现在连接已经关闭,而 DBManager 的实例仍然存在但没有用。我是否需要通过例如将其分配给 null 来销毁它?否则以后可能会被错误引用。

如果我为该实例分配 null,然后再次调用 newInstance 方法,我会得到另一个新的不同实例吗?

4

8 回答 8

10

我不会纠结于“单例”的语义——您的要求是DBManager任何时候最多存在一个实例。一旦该实例变得无用,您可以销毁它以便按需创建一个新实例,或者定义您的newInstance方法(我可能建议将其重命名getInstance)以抛出异常(也许IllegalStateException)如果在单例之后调用它有变得无用。

如果你打算在它变得无用时销毁它,我建议在单例类中自动完成,无需外部帮助。您还应该考虑完全隐藏单例DBManager并实现委托模式。这将避免客户端保留对陈旧DBManager实例的引用的问题。然后,您可以使委托对象成为常规单例。

于 2011-03-17T16:55:50.290 回答
5

我认为,您不能销毁单例,因为在任何时候都需要恰好有一个可用的实例。并且可以说它需要是同一个实例,否则它就不是一个真正的单例(例如,两个不同的类可以持有对该类不同实例的引用)。

但顺便说一句,这是我认为单例模式在实际软件中几乎没有用处的众多原因之一。在任何情况下,你都想要一件事,以至于你通过阻止人们调用构造函数来强制执行这一点的可能性 - 太死板了。这听起来像是一种情况,在某一时刻拥有一个单例似乎是合理的,但现在很明显多个实例是有意义的。

所以想一想这是否必须是一个单例——你能简单地把它做成一个适当的连接的包装器吗?

于 2011-03-17T16:50:12.940 回答
2

我认为让 DBManager 能够打开和关闭连接而不实际破坏 DBManager 本身会更符合 Singleton 模式。然后,您将保留它直到下一次需要数据库连接时,并要求同一个 DBManager 对象创建新连接。毕竟,如果是 DBManager,它管理连接;它不代表任何个人联系。

于 2011-03-17T16:50:49.257 回答
2

在这种情况下,我们使用连接池机制。您查询数据库的每个操作都必须打开和关闭连接。但是,因为我们正在使用连接池,所以连接会返回到池中,而不是物理关闭。

池上会有一个名为IDLE_CONNECTION_TIMEOUT或类似的设置,如果它们在配置的时间段内未使用,它将自动过期并关闭连接。因此,在这种情况下,开发人员无需担心。

于 2011-03-17T16:51:22.803 回答
0

简短的回答:没有。

更长的答案:你不能销毁一个单例,除非你使用一个特殊的类加载器。如果需要销毁它,则根本不应该使用单例。也许你可以重写它以重新打开它 - 更好:避免单例模式。

搜索反模式或代码异味。

于 2011-03-17T16:55:38.727 回答
0

如果数据库连接关闭,您的 DBManager 类应该处理清理工作。即如果 DBManager 有对 Connection 类的引用,那么您可以在 newInstance() 方法中编写代码来检查连接是否处于活动状态,然后返回静态引用。像这样的东西:

static DBManager manager;
static DBManager newInstance(){
if (manager == null) manager =new DBManager();
else if ( manager !=null && connection ==null) //if connection is closed 
manager =new DBManager();

return manager;
}
于 2011-03-17T17:00:46.080 回答
0

答案应该是,你不能摧毁一个单例,因为应该只有一个和一个。至于您的问题,您有一个 DBManager 类,该 HASA 连接已关闭并变得无用。

我猜你的目标应该是在任何时候打开一个数据库连接,所以我会在这里查看你的代码,你是否打破了单一责任主体并确保你将连接责任分成一个单独的类和允许您的单身管理其连接的特权 - 即在必要时关闭并重新打开它。

于 2011-03-17T17:02:32.943 回答
-1

为类变量创建一个 getter/setter 并将其设置为 null 以重新实例化一个对象 例如:

//Singleton support ...
private static A singleton = null;
    public static A get() {
        if (singleton == null){
        singleton = new A();
    }
        return singleton;
}
public static A getSingleton() {
    return singleton;
}
public static void setSingleton(A singleton) {
    A.singleton = singleton;
}

//Re instantiate 
public class Test(){
....
....
    A.setSingleton(null);

}
于 2012-05-16T19:10:25.887 回答