28

I understand that a singleton class is one where there can be only one instantiation, but I don't understand why this would be useful. Why won't you just create a class with static variables and methods and use synchronize if needed to make sure that no two threads were executing a method in the class simultaneously. I just don't get why anyone would go through the trouble of creating this kind of class. I know I'm missing something here.

Thanks,

skaffman
  • 398,947
  • 96
  • 818
  • 769
Elliott
  • 5,523
  • 10
  • 48
  • 87
  • 1
    making sure you'll only ever have one instance of a class is *very* important for things that are tied to the lifecycle of an application (that is: you only ever need one instance of some particular classes per launch of the application. In such a case it's a mistake two instantiate such a class twice but it is also a very gross programmer mistake to make more than one such instantiation possible). Some people use singleton for that but the main issue is that is complicates testing and especially unit testing. – SyntaxT3rr0r Feb 12 '11 at 18:13
  • 1
    @SyntaxT3rr0r: Most instances should actually not be tied to the lifecycle of an application, but rather to the lifecycle of a module or a specific scope (e.g. request scope for web apps). Otherwise, it's often not possible to reuse e.g. the code from a standalone app in a web app. // When you think about it, using a *ClassLoader* to guarantee Singleton semantics is really a weird idea in many cases. Just write a normal class (i.e. make it possible to instantiate it multiple times), and then let a dependency injection module be responsible to guarantee Singleton semantics within a scope. – Chris Lercher Feb 13 '11 at 13:39

11 Answers11

14

While I agree with the other answers, the OP was asking why not have a class with all static methods (possibly with static fields) instead of a singleton where you have one instance.

Why use Singletons?

You can Google "singleton" to find all sorts of reasons. From JavaWorld:

Sometimes it's appropriate to have exactly one instance of a class: window managers, print spoolers, and filesystems are prototypical examples. Typically, those types of objects—known as singletons—are accessed by disparate objects throughout a software system, and therefore require a global point of access. Of course, just when you're certain you will never need more than one instance, it's a good bet you'll change your mind.

Why use a Singleton instead of a class with all static methods?

A few reasons

  1. You could use inheritance
  2. You can use interfaces
  3. It makes it easier to do unit testing of the singleton class itself
  4. It makes it possible to do unit testing of code that depends on the singleton

For #3, if your Singleton was a database connection pool, you want to insure that your application has only one instance, but do unit testing of the database connection pool itself without hitting the database (possibly by using a package-scope constructor or static creational method):

public class DatabaseConnectionPool {
  private static class SingletonHolder {
    public static DatabaseConnectionPool instance = new DatabaseConnectionPool(
        new MySqlStatementSupplier());
  }

  private final Supplier<Statement> statementSupplier;

  private DatabaseConnectionPool(Supplier<Statement> statementSupplier) {
    this.statementSupplier = statementSupplier;
  }

  /* Visibile for testing */
  static DatabaseConnectionPool createInstanceForTest(Supplier<Statement> s) {
    return new DatabaseConnectionPool(s);
  }

  public static DatabaseConnectionPool getInstance() {
    return SingletonHolder.instance;
  }

  // more code here
}

(notice the use of the Initialization On Demand Holder pattern)

You can then do testing of the DatabaseConnectionPool by using the package-scope createInstanceForTest method.

Note, however, that having a static getInstance() method can cause "static cling", where code that depends on your singleton cannot be unit tested. Static singletons are often not considered a good practice because of this (see this blog post)

Instead, you could use a dependency injection framework like Spring or Guice to insure that your class has only one instance in production, while still allowing code that uses the class to be testable. Since the methods in the Singleton aren't static, you could use a mocking framework like JMock to mock your singleton in tests.

NamshubWriter
  • 23,549
  • 2
  • 41
  • 59
4

A class with only static methods (and a private contructor) is a variant where there is no instance at all (0 instances).

A singleton is a class for which there is exactly 1 instance.

Those are different things and have different use cases. The most important thing is state. A singleton typically guards access to something of which there is logically only ever one. For instance, -the- screen in an application might be represented by a singleton. When the singleton is created, resources and connections to this one thing are initialized.

This is a big difference with a utility class with static methods - there is no state involved there. If there was, you would have to check (in a synchronized block) if the state was already created and then initialize it on demand (lazily). For some problems this is indeed a solution, but you pay for it in terms of overhead for each method call.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • If you were that worried about lazy initialisation (why???) and didn't want the initialisation to occur when the class is initialised (why not???), then you could bung you initialisation into a nested class. In this unlikely circumstance, some forwarding would be necessary on the implementation side, but with a singleton the client code has to do it at every use site. – Tom Hawtin - tackline Feb 12 '11 at 17:08
  • *If you were that worried about lazy initialisation (why???)* - First of all it's not the lazy initialization itself that's primarily problematic, but the associated cost of having to do a synchronized check with each call. This causes lock contention and might diminish your potential throughput. – Arjan Tijms Feb 12 '11 at 17:39
  • You can also initialize the class state in a static initializer (`static { ... }`). – Paŭlo Ebermann Feb 12 '11 at 17:42
  • *didn't want the initialisation to occur when the class is initialised (why not???)* - uhm, the initialization of course occurs when the initialization occurs. That's in the very meaning of the word. The thing is, -when- does this happen. With a singleton it happens when the instance is requested from typically a factory. At that point initialization might occur. Once the instance is obtained however, clients can hold on to this instance and no further initialization nor checks for initialization will occur. – Arjan Tijms Feb 12 '11 at 17:43
  • *You can also initialize the class state in a static initializer* - True, you could, or you could use the modern variant with an enumeration and its ctor. The thing is that static initializers can be a rather crude mechanism. They very much hardcode the initialization to this block, which needs to have all the data inside the class to its work. Ok, it could depend on yet another static method in some class to possibly get some data from (the simplest being e.g. System.getProperty()), but the thing is that this just doesn't work for all cases. – Arjan Tijms Feb 12 '11 at 17:51
  • @arjan You could use the Initialization On Demand Holder idiom to avoid doing a synchronized check with each call (see http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl). Very good point on needing to get all of the data into the initialization block. You also have to worry about the initialization block throwing exceptions, which cause the class to fail to load – NamshubWriter Feb 13 '11 at 18:25
1

Database instances is one place singletons are useful, since a thread only wants one DB connection. I bet there are a lot of other instances like database connections where you only want one instance of something and this is where you would use a singleton.

Eddie
  • 141
  • 7
1

Use the singleton pattern to encapsulate a resource that should only ever be created (initialised) once per application. You usually do this for resources that manage access to a shared entity, such as a database. A singleton can control how many concurrent threads can access that shared resource. i.e. because there is a single database connection pool it can control how many database connections are handed out to those threads that want them. A Logger is another example, whereby the logger ensures that access to the shared resource (an external file) can be managed appropriately. Oftentimes singletons are also used to load resources that are expensive (slow) to create.

You typically create a singleton like so, synchronising on getInstance:

public class Singleton {

    private static Singleton instance;

    private Singleton(){
         // create resource here
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }

        return instance;
    }
}

But it is equally valid to create it like so,

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton(){
        // create resource here
    }

    public static Singleton getInstance() {
        return instance;
    }
}

Both methods will create a single instance PER classloader.

Joel
  • 29,538
  • 35
  • 110
  • 138
  • 2
    If the singleton you're creating is based on an interface and you're using Java 1.5+, consider using `enum`. For example `public enum Singleton implements SingletonContract { INSTANCE; /* interface method implementations and such here */ }` – Esko Feb 12 '11 at 16:26
  • 1
    @Joel, it should be noted that there is a difference between `Singleton` and `singleton`. Some people call `Singleton` - a GOF pattern (the one you're describing) and its usage scenarios. It is discussable but this GOF pattern is sometimes considered an antipattern. The class having exactly one instance is called `singleton`. `Singletons` can be easily replaced by classes with the single instance. – Alex Nikolaenkov Feb 12 '11 at 16:30
  • @Alex - You mean having a normal class but using an IOC container to ensure only a single instance is created? Very true. But the Singleton pattern is still useful and worth knowing. It's such a good pattern that many newer languages such as Scala have it baked in to the language. – Joel Feb 12 '11 at 16:33
  • I'm afraid that the first example isn't thread-safe with multiple classloaders either. Static methods synchronize on the class object, but there will be different class objects for different classloaders, so synchronization won't work properly. I can't think of an elegant workaround, though. – Sergei Tachenov Feb 12 '11 at 16:34
  • @Sergey - Thanks for pointing this out, I've updated accordingly. – Joel Feb 12 '11 at 16:36
  • The two code snippets have a key difference; they construct the instance at different points. If the constructor is expensive and the object is often not needed by the application at all, it can be better to use the first snippet (on the principle of letting the cost be borne by those that need it). – Donal Fellows Feb 13 '11 at 12:30
1

For me the reason to prefer singleton over a class with static methods is testability. Let's say that I actually need to ensure that there really is one and only one instance of a class. I could do that with either a singleton or a static class with only static methods. Let's also say that I'd like to use this class in another class, but for testing purposes I'd like to mock the first class out. The only way to do that is to inject an instance of the class into the second class and that requires that you have a non-static class. You still have some pain with respect to testing -- you might need to build in some code you can invoke with reflection to delete the singleton for test purposes. You can also use interfaces (though that would explicitly would allow the use of something other than the singleton by another developer) and simply provide the singleton as an instance of the interface to the class that uses it.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
1

One consideration is that making a singleton an instance allows you to implement an interface. Just because you want to control instantiation to it, does not mean you want every piece of code to know that it's a singleton.

For example, imagine you had a connection provider singleton that creates DB connections.

public class DBConnectionProvider implements ConnectionProvider {}

If it were a class with static methods, you couldn't inject the dependency, like this:

public void doSomeDatabaseAction(ConnectionProvider cp) {
   cp.createConnection().execute("DROP blah;");
}

It would have to be

public void doSomeDatabaseAction() {
   DBConnectionProvider.createConnection().execute("DROP blah;");
}

Dependency injection is useful if you later want to unit test your method (you could pass in a mocked connection provider instead) among other things.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
0

A singleton has the advantatage over a class with static variables and methods : it's an object instance, which can inherit from a class (example : an application that ahas a single principal JFrame), and extend one or more interfaces (and thus be treated as any other object implementing these interfaces).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 1
    Since it's an instance, it can also be Mocked. Mocking static functions takes more effort. – KitsuneYMG Feb 12 '11 at 16:25
  • @KitsuneYMG So the mock would be a second instance of your singleton? – Tom Hawtin - tackline Feb 12 '11 at 17:09
  • Making it a singleton gives you the possibility to choose between implementations in the getInstance() method - for testing, the mock is returned, otherwise the real thing. How you do that is a different question. – Axel Feb 12 '11 at 17:24
0

When would you need to use one? There are many objects we only need one of: thread pools, caches, dialog boxes, objects that handle preferences and registry settings, objects used for logging, and objects that act as device drivers to devices like printers and graphic cards. For many of these types of object if we were to intantiate more than one we would run intol all sorts of problems like incorrect program behavior or overuse of resources

Regarding the usage of synchronization it is definitly expensive and the only time syncrhonization is relevant is for the first time or the unique instatiation once instantiated we have no further need to synchronize again. After the first time through, syncrhonization is totally unneeded overhead :(

Bartzilla
  • 2,768
  • 4
  • 28
  • 37
  • I wouldn't say that synchronization is totally unneeded. If the singleton provides access to a shared resource, then some synchronization must take place. I agree that you don't have to synchronize everything, though. – Sergei Tachenov Feb 12 '11 at 17:01
  • @Sergey - I agree, what I am trying to expose is that “if in multithreading environment” as the question states; then simply the usage synchronization in some cases will not be the best. Certainly you can do that if the instantiation isn’t causing substantial overhead in the application. But if it does you might want to decrease this performance impact by using other options like either moving to an eagerly created instance or “double-check locking” to reduce the use of synchronization. – Bartzilla Feb 12 '11 at 18:48
  • unfortunately, [DCL is completely broken in Java](http://www.ibm.com/developerworks/java/library/j-dcl.html). – Sergei Tachenov Feb 12 '11 at 18:55
  • @Sergey - If you use a JVM other than Java 5 consider other methods (other than DCL) to implement Singleton. **Head First Design Patterns. Item 5: Dealing with multithreading.** Here is a thread that shows how to implement DCL in Java 5 or higher [How to solve DCL in java](http://stackoverflow.com/questions/3578604/how-to-solve-the-double-checked-locking-is-broken-declaration-in-java) taken from **Effective Java, Second Edition** which is basically the purpose of DCL – Bartzilla Feb 12 '11 at 19:33
0

Some people think that singletons are useless and dangerous. I don't completely agree, but some points about it are valid, and singletons should be used carefully.

Static classes used in place of singletons are even worse in my opinion. Static classes should be mainly used to group related functions which don't share a common resource. java.util.Collections is a good example. It's just a bunch of functions that aren't tied to any object.

Singletons, on the other hand, are true objects. Ideally, singleton should be implemented without singleton pattern in mind. This will allow you to easily switch to using multiple instances if you suddenly need it. For example, you may have only one database connection, but then you have to work with another, completely unrelated database at the same time. You just turn your singleton into a "doubleton" or "tripleton" or whatever. If you need, you can also make its constructor public which will allow creation of as many instances as you want. All this stuff isn't so easy to implement with static classes.

Simply put, a singleton is a regular class that has one instance globally available, to save you from all the trouble of passing it everywhere as a parameter.

And there is not much trouble in creating a singleton. You just create a regular class with a private constructor, then implement one factory method, and you're done.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
0

Others have provided better answers while I was replying, but I'll leave my answer for posterity. It would appear unit testing is the big motivator here.

For all intents and purposes, there is no reason to prefer a singleton to the approach you described. Someone decided that static variables are capital-b Bad (like other sometimes useful features like gotos) because they're not far off from global data and in response we have the workaround of singletons.

Bradley Swain
  • 804
  • 5
  • 12
0

They are also used with other patterns. See Can an observable class be constructed as a singleton?

Community
  • 1
  • 1
simpatico
  • 10,709
  • 20
  • 81
  • 126