5

I want to know, how to use the singleton pattern with interfaces? I have created an interface:

public interface BusinessService {

   BusinessService getInstance();

}

I make this implementation:

public class BusinessServiceImpl implements BusinessService {

  private static BusinessServiceImpl instance = null;

  private BusinessServiceImpl(){ }

  @Override
  public BusinessServiceImpl getInstance() {
    if (instance == null) {
        BusinessServiceImpl.instance = new BusinessServiceImpl();
    }
    return BusinessServiceImpl.instance;
  }
}

How can I get access to getInstance from my main-class? I tried something like

private BusinessService service = new BusinessServiceImpl();

(does not work - Constructor from BusinessServiceImpl() is private)

But what else? Can you help me out?

Edit: I'm using Java Spring! I don't want to use Java Springs - Dependency Injection!

Greets, Mira

cngzz1
  • 143
  • 2
  • 9
Mira Mira
  • 1,385
  • 3
  • 11
  • 18
  • You got a `NullPointerException` from that? Where is the stack trace? – khelwood Aug 22 '16 at 08:30
  • You should use a dependency-injection tool like Spring or Guice. – chrylis -cautiouslyoptimistic- Aug 22 '16 at 08:33
  • 3
    If "BusinessSericeImpl" is singleton, you cannot call "new BuisinessServiceImpl()". You should do BuisinessServiceImpl.getInstance(); Which you cannot, because the getInstance method is not static. You cannot define static methods in interfaces. Are you sure you want singleton? It looks more like a factory pattern – mlecz Aug 22 '16 at 08:33
  • Make your `getInstance()` method static. and try to get the `BusinessService service = BusinessServiceImpl.getInstance()` – zstring Aug 22 '16 at 08:33
  • 1
    The getInstance() method must be static, and must thus not be part of the interface. Otherwise, you need to construct a new instance to get the unique instance, which makes no sense at all. Why do you want to use the singleton anti-pattern in the first place? – JB Nizet Aug 22 '16 at 08:34

1 Answers1

14

The code you have provided is a bit mixed - up.

The whole point of controlling the instantiation of your singleton class means that you have to hide your constructor, so clients can't access it and create new instance at will.

Your factory method (a method, that creates the instance of your class) getInstance() is an instance method. You have to create a new instance of BusinessService in order to create an instance of BusinessService - it's pretty obvious that won't work properly.

You have a few options to deal with your situation:

  1. Remove the getInstance() method from your interface and expose it in your implementation class as a static method. You should also limit the visibility of the constructor to private.

    public class BusinessServiceImpl implements BusinessService {
    
        public static BusinessServiceImpl getInstance() {
            // instantiation logic
        }
    
        private BusinessServiceImpl() {
            // constructor logic
        }
    }
    
  2. Use a factory class to instantiate your service and control the number of instances. This includes removing the getInstance() method all together and limiting the visibility of your BusinessServiceImpl class to package.

    class BusinessServiceImpl implements BusinessService {
    
        BusinessServiceImpl() {
            // constructor logic
        }
    }
    
    // should be in the same package as BusinessServiceImpl
    public final class BusinessServiceFactory {
    
        private BusinessServiceImpl instance;
    
        public BusinessService getInstance() {
            // instance creation logic, same as singleton creation logic
        }
    
    }
    
  3. Use an enum to deal with the singleton logic. Remove the getInstance() method from your interface.

    public enum BusinessServiceImpl implements BusinessService {
    
        INSTANCE;
    
        // implement the methods from your interface
    }
    
Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
  • 1
    Nice answer. Option 1. would be the standard one, only you may prefer that `getInstance()` return `BusinessService` as in the question. I would consider 2. overcomplex for the requirements and reserve it for more complex situations. Number 3. is elegant, though not standard `enum`use. – Ole V.V. Aug 22 '16 at 08:56
  • Ok, thanks. possibly i have problems to get singleton pattern work, because im trying it to involve in Java Spring. When I'm using the Annotations, it works well. But i want to get it work, without the annotation. – Mira Mira Aug 22 '16 at 09:11
  • All of the provided examples don't use any Spring related annotations. It just plain Java code. Analyse your requirements, access the complexity of the solutions and try one. – Danail Alexiev Aug 22 '16 at 10:25
  • Solution 2 is not recommend. [I was asking for advice](https://softwareengineering.stackexchange.com/questions/440004/should-i-design-a-factory-that-returns-a-singleton) doing this pattern with multiple implementations and a common factory class and got almost only constructive feedback which summarizes in: Do not mix up concepts (i.e. factory and singleton). I also got some advice to avoid to have one factory for multiple singleton implementations due to the fact that I would limit myself even further down the line, but this might not be relevant to this particular problem. – Martin Braun Jul 31 '22 at 10:38