Why Implementing a Singleton Pattern in Java Code Is (Sometimes) Considered an Anti-Pattern in Java World

Why implementing a Singleton pattern in Java code is (sometimes) considered an anti-pattern in Java world?

Testing

One reason is that singletons aren't easy to handle with unit tests. You can't control the instantiation and by their very nature may retain state across invocations.

For that reason the principle of dependency injection is popular. Each class is injected (configured) with the classes they need to function (rather than derive via singleton accessors) and so tests can control which dependent class instances to use (and provide mocks if required).

Frameworks such as Spring will control the lifecycle of their objects and often create singletons, but these objects are injected into their dependent objects by the framework. Thus the codebase itself doesn't treat the objects as singletons.

e.g. rather than this (for example)

public class Portfolio {
private Calculator calc = Calculator.getCalculator();
}

you would inject the calculator:

public class Portfolio {
public Portfolio(Calculator c) {
this.calc = c;
}
}

Thus the Portfolio object doesn't know/care about how many instances of the Calculator exist. Tests can inject a dummy Calculator that make testing easy.

Concurrency

By limiting yourself to one instance of an object, the options for threading are limited. Access to the singleton object may have to be guarded (e.g. via synchronisation). If you can maintain multiple instances of those objects, then you can tailor then number of instances to the threads you have running, and increase the concurrent capabilities of your codebase.

Singleton Design Pattern: Pitfalls

Singleton is generally a bad idea if you are doing unit testing, and its generally a bad idea not to do unit testing (or BDD or Acceptance Testing).

Making objects have global state means that the unit tests you write involving these objects will be isolated and disjoint from one another. Instead, you will have to worry about resetting the state for each test and believe me ... that is never done 100% of the time. If you don't reset the global state then you start to get very weird and hard to debug errors in your tests that waste time.

Global state also increases coupling in your code and makes it very hard to refactor.

The ideal method would be to use an IoC/DI container (Spring, Guice, etc.) to request objects. These containers often have ways of making objects appear as 'Singletons' but they also have ways of modifying that behavior depending on the situation (i.e. unit testing vs. your domain code).

This all depends on the size of your problem of course. If you're hacking together a 4-class test rig to try something out then go ahead and use a Singleton. However, as soon as that project takes on life and grows bigger and more complex then refactor the Singleton out.

What are drawbacks or disadvantages of singleton pattern?

Paraphrased from Brian Button:

  1. They are generally used as a global instance, why is that so bad? Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.

  2. They violate the single responsibility principle: by virtue of the fact that they control their own creation and lifecycle.

  3. They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.

  4. They carry state around for the lifetime of the application. Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no no for unit tests. Why? Because each unit test should be independent from the other.

Singleton's other members

One note is that it is important to distinguish between the concept of a singleton (a class/object that has only a single instance) and the design pattern which achieves this via a class holding a single static instance of itself accessible in the global static name space. The concept of a singleton is frequently used in designs, the implementation of it via the singleton design pattern, however, is often frowned upon.

In the below, singleton is used to refer to the specific design pattern.

Part 1

  1. A Singleton's members do not need to be static, and usually are not.
  2. See 1.
  3. A singleton (design pattern) requires an instance to itself in order to return that instance to users of the singleton, as well as keeping a reference to itself active to avoid garbage collection (as you suggest). Without this single instance, the object is essentially not an implementation of the singleton design pattern. You can create a class for which you only create a single instance and pass this class around where it is required (avoiding the global static namespace), and this would essentially be a recommended way to avoid using the singleton pattern.

Part 2:

Sharing your thread pools is probably wise (but depends on your requirements), and this can be done in a number of ways. One way would be to create a single pool and to pass this pool (inject it) into the classes that require it. Usual recommendation for this is to use something like Spring to handle this for you.

Using a singleton is also an option, but even if your thread pool here is encapsulated in a singleton, it is still generally preferable to inject this singleton (preferably referenced via an interface) into dependent objects (either via a setter or in their constructor) instead of having your objects refer to the singleton statically. There are various reasons for this, with testing, flexibility, and control over order of instantiation being some examples.

What is an efficient way to implement a singleton pattern in Java?

Use an enum:

public enum Foo {
INSTANCE;
}

Joshua Bloch explained this approach in his Effective Java Reloaded talk at Google I/O 2008: link to video. Also see slides 30-32 of his presentation (effective_java_reloaded.pdf):

The Right Way to Implement a Serializable Singleton

public enum Elvis {
INSTANCE;
private final String[] favoriteSongs =
{ "Hound Dog", "Heartbreak Hotel" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
}

Edit: An online portion of "Effective Java" says:

"This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton."

why are there java singleton classes? When would you need to use one

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.

what is the advantage of Singleton Design Pattern

To assure only one and same instance of object every time.

Take a scenario, say for a Company application, there is only one CEO. If you want to create or access CEO object, you should return the same CEO object every time.

One more, after logging into an application, current user must return same object every time.

When does an exception becomes considered as an anti-pattern?

When you have to allow something that doesn't fit your architecture, it means that there's something important you didn't know or failed to anticipate, and that your architecture can't accommodate that as designed.

Foresight fails all the time. You have to learn to live and deal with that. Yes, you need to learn everything you can about your customers and their needs, but that's always imperfect. A failure of foresight doesn't indicate any kind of problem with your process unless you'be been negligent, but still each one is an opportunity to learn something about your customers.

That the thing you missed is important is a little more troubling. When there are regulatory requirements in the domain you're designing for, and you don't know about them, and they restrict what you can build... that kinda sounds like something you should have known. I don't know your specific business, though, so maybe there's a reason why that's not true for you.

That your architecture can't accommodate the things you didn't anticipate is the real issue. You should always strive to ensure that the things you don't know or can't anticipate are inconsequential to the overall architecture. This is the part you should really think about: "What assumption did I bake into this architecture that makes it rigid in this dimension? How could I have made my architecture work without presuming to know this stuff that I didn't know?"

Figuring out answers to these questions, and testing those answers in your next project, will make you better every year.



Related Topics



Leave a reply



Submit