3

I know there has been 1 million and 1 discussions about Singletons on SO and here and I have had to clean up my fair share of terrible singletons in our code base; one of the reasons I am gun-shy here. But I am running into a situation where I feel like a Singleton is a reasonable solution and wanted to see what others think.

Quick setup: we have a set of interfaces which extend the Java functional interfaces of Consumer, Function, etc. to make the semantics cleaner mostly. One of these is as follows. JaxbClass is a POJO from the Jaxb generated XML bindings and KbType is an Enum used load data down. Pretty much a way of wrapping the binding classes with logic.

public interface KbTypeMapper extends Function<T extends JaxbClass, KbType>{}

Most classes which implement this interface do keep track of some internal state and so being able to have multiple instances of these classes is required, but for the current class I am implementing there is no internal state so there is no reason to ever instantiate more than one object of this class.

Objects which implement this interface are usually injected as dependencies and I would not change this for this one class. The param signature for most places this injection happens is something along the lines of Function<T,KbType>. I would just replace instances like this:

SomeClass x = new SomeClass(new SpecificKbTypeMapper())

With:

SomeClass x = new SomeClass(SpecificKbTypeMapper.instance())

I could turn this into a static utility type class and just inject StaticUtilility::functionName but then that would not fit with the overall design and would not actually implement our own interface which I think would be confusing.

I don't see a problem testing the class itself nor mocking the class since the single instance is still being injected where it is actually used.

Am I completely wrong in that a singleton is a perfectly fine solution here? Or am I just over engineering and should just keep a bunch of new object instantiations?

  • 2
    Considering the advantage you'd be getting from a singleton, i.e. save a few bytes of memory, you're wasting your developer bang on too little buck. – Kayaman Jun 13 '18 at 5:38
  • 1
    Why does it matter that you get the same object when it has no state? – Caleth Jun 13 '18 at 9:06
  • 1
    The more I think about it the more I am coming to the same conclusion that it is over engineering for the sake doing something 'fancy'. And given the amount of 'fancy' code I have had to debug and clean up in the past the less I want to deal with this in a year's time! – Hangman4358 Jun 13 '18 at 13:11
2

The worst singleton problem after shared mutable state is a reference, which cannot be parametrized.

Use of stateless singleton is equivalent to use of ad-hoc instantiated class. Both are perfectly valid, if decoupling is deemed unnecessary. If decoupling is necessary, both would work fine, being injected in top level code, as @orange demostrates.

In other words, problems of stateless singleton are not in its implementation, but in usage pattern, and are not different from usual malpractice of ad-hoc instatiation of complex dependencies.

Whatever you write in implementation, you won't take away from clients an ability to pollute code base with unjustified direct references. Just relax, document intended usage pattern and stay alert on code reviews.

  • I chose this answer because I think it more directly related to my question of over engineering. Though I think @candied_orange makes a very valid point. If anything, I would like to smash the two together: a simple counter example + in-depth response. – Hangman4358 Jun 13 '18 at 13:19
3

My design for an alternative to singleton: static construction

public static void main() {
    KbTypeMapper singleKbTypeMapper = new SpecificKbTypeMapper();
    SomeClass x = new SomeClass(singleKbTypeMapper);
    SomeOtherClass y = new SomeOtherClass(x, singleKbTypeMapper);

    y.doSomethingFun():
}

Now I'm not saying factories can't help hide complexity. I just don't need or want them telling me how many instances I can have. I'll decide that myself.

  • So a hybrid of this approach and a Singleton may be to instantiate a public static final instance of the class which can be used in most cases but also still allow creation of new instances along the vain of Boolean.TRUE while still being able to instantiate new Boolean(true) if you want to for some reason and then document preferred usage as per @Basilevs answer? – Hangman4358 Jun 13 '18 at 5:36
  • Admittedly, hybrid approach would be less readable at if you DO introduce state in singleton. Casual user would have a knee-jerk reaction of using singleton reference, ignoring documented requirements. This is less probable with explicit construction. – Basilevs Jun 13 '18 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.