2

How to design Java classes that can possibly function as Singleton?

 2 years ago
source link: https://www.codesd.com/item/how-to-design-java-classes-that-can-possibly-function-as-singleton.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How to design Java classes that can possibly function as Singleton?

advertisements

Here's the scenario:

public class A {
    public A {}
    void doSomething() {
        // do something here...
    }
}

Right now, the class is setup where you can create multiple instances. But I also see a need where I might want to restrict the class to only one instance, i.e. Singleton class.

The problem is I'm not sure how to go about the design of accomplishing both goals: Multiple instances and one instance. It doesn't sound possible to do in just one class. I imagine I'll need to use a derived class, an abstract class, interface, something else, or some combination.

Should I create class A as a base class and create a derived class which functions as the singleton class?


Of course, the first thing should always be to question the necessity to use singletons. But sometimes, they are simply a pragmatic way to solve certain problems.

If so, the first thing to understand is: there is no solution that can "enforce" your requirements and prevent mis-use, but here is a "pattern" that helps a lot by turning "intentions" into "meaningful" code:

First, I have an interface that denotes the functionality:

interface WhateverService { void foo() }

Then, I have some impl for that:

class WhateverServiceImpl implements WhateverService {
  @Override
  void foo() { .... }

Now, if I need that thing to exist as singleton, I do

enum WhateverServiceProvider implements WhateverService {
  INSTANCE;
  private final WhateverService impl = new WhateverServiceImpl();
  @Override
  void foo() { impl.foo() }

and finally, some client code can do:

WhateverService service = WhateverServiceProvider.INSTANCE;
service.foo()

(but of course, you might not want to directly assign a service object, but you could use dependency injection here)

Such architectures give you:

  1. A clear separation between the core functionality, its implementation and the singleton concept
  2. Guaranteed singleton semantics (if there is one thing that Java enums are really good for ... then it is that: providing fool-proof singletons!)
  3. Full "testability" (you see - when you just use the enum, without making it available as interface ... then you have a hard time mocking that object in client code - as you can't mock enums directly).

Update - regarding thread safety:

I am not sure what exactly you mean with "singleton concept".

But lets say this: it is guaranteed that there is exactly one INSTANCE object instantiated when you use enums like that, the Java language guarantees that. But: if several threads are turning to the enum, and calling foo() in parallel ... you are still dealing with all the potential problems around such scenarios. So, yes, enum "creation" is thread-safe; but what your code is doing ... is up to you. So is then locking or whatever else makes sense.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK