2

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?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
user3621633
  • 1,681
  • 3
  • 32
  • 46
  • 6
    Why do you think you need a singleton (http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons)? – Andy Turner Jul 22 '16 at 14:11
  • 2
    Optionally? Are you suggesting that they change to Singleton like stem cells? Singleton isn't a good idea. You'd be better off rethinking your requirements. Sounds like unnecessary complexity for its own sake. – duffymo Jul 22 '16 at 14:13
  • 1
    Both situation are simultaneously possible? A part of code use the class creating new object and another part use the "Singleton"? The part that uses multiple istances share them between threads? My doubt is that this is not properly a Singleton implementation. – Aris2World Jul 22 '16 at 14:21
  • I don't know if I need a Singleton. But there is a usecase where I want the developer to leverage the class such that only one instance is possible. But there is another usecase for the same purpose of the class, where it can have multiple instances. It's about flexibility. But I would expect to accomplish both in one class not only would be poor practice but probably not feasible. Hence, why I brought up using derived classes, abstract classes, and the like. – user3621633 Jul 22 '16 at 14:29

3 Answers3

3

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.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Quite a remarkable solution! To be frank, I'm not very familiar with utilizing `enum` and the _singleton concept_. Just to confirm, this solution is thread-safe and does strictly adhere to the _singleton concept_? Thank you. – user3621633 Jul 22 '16 at 17:11
  • Ahh, that's pretty clear. Thank you. By _singleton concept_, I'm referring to the `Singleton` pattern, i.e. the requirements to be be a Singleton class. I see many Singleton examples that use a private empty constructor. I don't see that here. – user3621633 Jul 22 '16 at 17:37
  • You can use the same "pattern"; and simply turn the "impl" class into a singleton directly by using private constructors/static methods. And please note: this is more of "convention". If a user changes the enum and adds a second enum INSTANCE2 ... so: that is a bit easier to mess up than other solutions. – GhostCat Jul 23 '16 at 12:52
2

I think you should take a look at this question: Can a constructor in Java be private?

The Builder pattern described there could be a somewhat interesting solution:

// This is the class that will be produced by the builder
   public class NameOfClassBeingCreated {
      // ...

      // This is the builder object
      public static class Builder {
        // ...

        // Each builder has at least one "setter" function for choosing the
        // various different configuration options. These setters are used
        // to choose each of the various pieces of configuration independently.
        // It is pretty typical for these setter functions to return the builder
        // object, itself, so that the invocations can be chained together as in:
        //
        //     return NameOfClassBeingCreated
        //         .newBuilder()
        //         .setOption1(option1)
        //         .setOption3(option3)
        //         .build();
        //
        // Note that any subset (or none) of these setters may actually be invoked
        // when code uses the builer to construct the object in question.
        public Builder setOption1(Option1Type option1) {
           // ...
           return this;
        }

        public Builder setOption2(Option2Type option2) {
           // ...
           return this;
        }

        // ...

        public Builder setOptionN(OptionNType optionN) {
           // ...
           return this;
        }

        // ...

        // Every builder must have a method that builds the object.
        public NameOfClassBeingCreated build() {
           // ...
        }

        // The Builder is typically not constructible directly
        // in order to force construction through "newBuilder".
        // See the documentation of "newBuilder" for an explanation.
        private Builder() {}
      }

      // Constructs an instance of the builder object. This could
      // take parameters if a subset of the parameters are required.
      // This method is used instead of using "new Builder()" to make
      // the interface for using this less awkward in the presence
      // of method chaining. E.g., doing "(new Foo.Builder()).build()"
      // is a little more awkward than "Foo.newBuilder().build()".
      public static Builder newBuilder() {
         return new Builder();
      }

      // ...

      // There is typically just one constructor for the class being
      // constructed that is private so that it may only be invoked
      // by the Builder's "build()" function. The use of the builder
      // allows for the class's actual constructor to be simplified.
      private NameOfClassBeingCreated(
          Option1Type option1,
          Option2Type option2,
          // ...
          OptionNType optionN) {
        // ...
      }
   }

Link for reference: https://www.michaelsafyan.com/tech/design/patterns/builder

Community
  • 1
  • 1
Julian
  • 344
  • 1
  • 11
  • These are excellent resources! Thank you. I'm not entirely sure the Builder design pattern is the best tool here, given my extremely simple class example, but I will definitely study this and keep it in my toolbox. Thanks, again! – user3621633 Jul 22 '16 at 15:08
  • 1
    No problem man. Please evaluate the best answer in your opinion. – Julian Jul 22 '16 at 15:13
1

I am not sure that this is what you are looking for, but you can use Factory pattern. Create 2 factories, one will always return the same singleton, while the other one will create a new A object each time.

Factory singletonFactory = new SingetonFactory();
Factory prototypeFactory = new PrototypeFactory();

A a = singletonFactory.createA();
A b = singletonFactory.createA();
System.out.println(a == b); // true

A c = prototypeFactory.createA();
A d = prototypeFactory.createA();
System.out.println(c == d); // false


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

interface Factory {
    A createA();
}

class SingetonFactory implements Factory {
    private final A singleton = new A();

    public A createA() {
        return singleton;
    }
}

class PrototypeFactory implements Factory {
    public A createA() {
        return new A();
    }
}
noscreenname
  • 3,314
  • 22
  • 30
  • Interesting solution. This looks quite feasible and easy to manage and expand. Thank you. Is `SingletonFactory` technically `Singleton` implementation? And is it thread-safe? – user3621633 Jul 22 '16 at 14:58
  • 1
    Technically no, you can create multiple `SingletonFactory` instances, each one providing a different A object. It is thread safe, because singleton field is final. – noscreenname Jul 22 '16 at 15:14