15

By using a singleton, only one instance of it can be created. Do we ever need to destroy that instance?

I have a singleton DBManager, which manages a JDBC connection and query operations. By calling its static newInstance method, I can get the instance of it, then I do some queries. Finally, I want to close the Database connection, and I call another static method close to close the JDBC connection.

Now the connection has been closed, while the instance of DBManager is still alive but not useful. Do I need to destroy it by for example assigning it to null? Otherwise it may be referenced by mistake later on.

If I assign that instance with null, then call newInstance method again, will I get another new different instance?

John Fisher
  • 22,355
  • 2
  • 39
  • 64
chance
  • 6,307
  • 13
  • 46
  • 70

8 Answers8

11

I wouldn't get hung up over the semantics of “singleton”—your requirement is that at most one instance of DBManager exist at any time. Once that instance is rendered useless, you can either destroy it so a fresh instance will be created on demand, or else define your newInstance method (which I might suggest be renamed getInstance) to throw an exception (perhaps IllegalStateException) if it is called after the singleton has been rendered useless.

If you are going to destroy it when rendered useless, I suggest that this be done inside the singleton class automatically, with no outside help. You also should consider completely hiding the singleton DBManager and implementing a delegation pattern instead. This will avoid the problem of a client keeping a reference to the stale DBManager instance. You can then make the delegate object a regular singleton.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
5

I'd argue that no, you can't destroy a singleton because there needs to be exactly one instance of it available at all times. And arguably it needs to be the same instance, because otherwise it's not really a singleton (e.g. two different classes could hold references to distinct instances of the class).

But incidentally, this is one of the many reasons why I believe the singleton pattern has little to no use in real software. The odds of you wanting exactly one thing, ever, in all circumstances, to the point where you enforce this by preventing people from calling constructors - is just too rigid. This sounds like a situation where at one point it seemed reasonable to have a singleton, but it's now become evident that multiple instances makes sense.

So think about whether this must be a singleton - can you simply make it a wrapper around the connection that's wired in as appropriate?

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 1
    It might make sense in this case to have a Singleton for a connection pooling mechanism such as adarshr mentions. You will only ever have one connection pool, and this seems like the right class to handle it. I agree with you on the basic content of your post, and in fact when explaining Singleton to a small-ish group not familiar with design patterns, I ran into many potholes based on all of the cases where Singletons are inappropriate or just plain nonsensical. – jprete Mar 17 '11 at 16:59
  • 1
    @jprete Many years ago I worked on an application that use one database. Then we wanted the code to use two databases. The application had singletons. We were completely hosed. – Tom Hawtin - tackline Mar 17 '11 at 17:36
  • 1
    @Tom: That kind of scenario was one of the things we were tripping over. My end conclusion was that I just shouldn't have talked about singletons at all. For me, this question, and Andrzej's answer in particular, really pokes holes in the idea that the singleton is a useful pattern. – jprete Mar 17 '11 at 18:04
  • 1
    The contract for Singleton says "at most one". Plenty of occasions where a Singleton creation is delayed until it is needed - it's one of the things that makes it (sometimes) better than a static utility class. – DJClayworth Mar 17 '11 at 19:34
2

I think it would be more in keeping with the Singleton pattern to make the DBManager capable of opening and closing the connection without actually destroying the DBManager itself. You would then keep it around until the next time you need a database connection, and ask the same DBManager object to create the new connection. After all, if it's a DBManager, it manages connections; it doesn't represent any individual connection.

jprete
  • 3,769
  • 21
  • 24
  • We were probably writing at the same time. I voted you down because you dragged class loaders into it, which will just confuse people. – jprete Mar 17 '11 at 17:58
  • Your first comment to mine showed '38 min ago' while this was '34 min ago'. Probably at the same time, yes. ;) – user unknown Mar 17 '11 at 18:28
  • I tend to spend a long time writing answers. I saw Andrzej's answer pop up while I was writing and had to verify that we had different answers. – jprete Mar 17 '11 at 18:37
  • +1 That explains perfectly, why you meanwhile commented my answer. – user unknown Mar 17 '11 at 18:46
2

In such cases, we make use of the Connection Pooling mechanism. Each of your operations which query the database must open and close the connection. However, because we're making use of the Connection Pool, the connection is returned to the pool instead of physically getting closed.

There will be a setting on the pool called IDLE_CONNECTION_TIMEOUT or similar which will automatically expire and close the connections if they're unused for the configured period of time. So, little for the developer to worry about in such cases.

adarshr
  • 61,315
  • 23
  • 138
  • 167
0

Short answer: No.

Longer answer: You cannot destroy a singleton, except you use a special Classloader. If you need to destroy it, you shouldn't use a singleton at all. Maybe you can rewrite it in a way to reopen it - better: avoid the singleton pattern.

Search for anti pattern, or code smell.

user unknown
  • 35,537
  • 11
  • 75
  • 121
  • -1 It's trivial to build a Singleton that can be destroyed. The programmer decides exactly how far the Singleton pattern will be followed (or not), and class loaders have little to do with it. – jprete Mar 17 '11 at 17:03
  • Singleton means, there is just one instance. If you look for the pattern, you will always find a solution which involves static in Java. And then you're stuck. What did the TO say himself about the situation? `By calling its static newInstance method, ...`. If you do something else, and call it still 'singleton', I wouldn't argue with you, but if the TO did have such a thing in mind, he wouldn't have asked the question, would he? – user unknown Mar 17 '11 at 17:42
  • 1
    Yes. And `newInstance()` can easily be implemented to create a new instance and stick it in a static field. At which point it's trivial to write a `deleteInstance()` method that nulls out the old one (and does other cleanup). This leaves `newInstance()` in a position to recreate the singleton from scratch. You can fairly argue that this is no longer a singleton, but the class loader is not preventing anyone from doing things this way. – jprete Mar 17 '11 at 18:01
  • Well, and it isn't far away from the second solution: allow to open and close the connection, which you successfully adopted. – user unknown Mar 17 '11 at 18:26
0

Your DBManager class should handle the cleanup if the db connection is closed. i.e if DBManager has a referrence to Connection class , then you can write a code in the newInstance() method to check if connection is alive then return static Reference. something like this:

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;
}
othman
  • 4,428
  • 6
  • 34
  • 45
0

The answer should be no you can't destroy a singleton as there should be one and one only. As to your problem, you have a DBManager class, which HASA connection that's closed and become useless.

I'm guessing your aim should be to have one DB connection open at any one time, so I would look at your code here, are you breaking the single responsibility principal and ensure that you split off the Connection responsibility in to a separate class and allow your single the privilege of managing its connections - i.e. closing and reopen it as necessary.

roghughe
  • 169
  • 4
-1

Create a getter/setter for the class Variable and set it yo null to re-instantiate an object Ex:

//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);

}
Abhi
  • 11
  • 1
  • 1
    What is the point of having a setter? Why not just a destroy method (that simply sets the singleton to null, with the advantage that you cannot try to set it to something else)?? – Renato May 17 '12 at 10:47