1

I have an UI module that will expose only one class - UserInterface. The class will be responsible for collecting user input and providing output (command line UI style). From logical way of thinking, I'd never need more than one instance of the UserInterface class.

Should I enforce only one instance using design like singleton pattern or just don't create more instances (sounds like a bad design to me)?

2 Answers 2

1

A singleton for your UserInterface makes only sense when all of the following conditions are met:

  • having more than one instance cannot be allowed, because that would cause a misfunction in the program if two of those objects exist at the same time

  • you know for sure you will never need inheritance for UserInterface.

If not both conditions are met, a singleton is either unsuitable or overdesigned. This is pretty often the case in real-world scemarios, that's why Singleton is often considered to be an anti-pattern.

Note also that when there are components depending on the "singleton candidate", passing the latter by constructor injection into the components / classes may simplify unit testing. By this kind of design, it does not make a huge difference if the injected object is a singleton or not. In case all the depending components are implemented that way, the "singleton mechanics" is probably not worth the hassle, since you can make sure there is only one object of the "singleton candidate" in "wiring up" part of the program.

4
  • what to do if I need unit tests and having more than one instance would break the application? I guess I'll have to design UserInterface some other way in order to prevent it from doing any "damage" if instantiated twice or so
    – Wiktor
    Commented May 14, 2021 at 12:00
  • @Wiktor: to be fair, a component which requires the single instance can be designed to be unit-testable even when the single-instance is a singleton. The component should just not make use of the Singleton mechanics to get the instance, but injected from outside. But when all users of the singleton get the instance injected, the classic Singleton mechanics becomes pretty useless.
    – Doc Brown
    Commented May 14, 2021 at 12:45
  • it's worth noticing that singleton doesn't have to be a class/interface with public static access. It could also be designed as a class with a static boolean hasBeenCreated check in the constructor (if true it could throw an exception)
    – Wiktor
    Commented May 14, 2021 at 14:35
  • @Wiktor: if a component uses x=MySingleton::getInstance() or x=new MySingleton() inside is not a huge difference in regards to unit testing that component (both variants make unit testing harder). If the component expects a single instance of UserInterface through its constructor, where UserInterface is actually an interface to the expected UserInterfaceImplementation object, then it will be easier to exchange the UserInterface by a mock for testing purposes.
    – Doc Brown
    Commented May 14, 2021 at 15:18
0

Don't use the singleton pattern. Ever. Just create one instance in some central place, like the main() method and pass that around.

If you are concerned people might instantiate your object in some other way and mess with the rest of your sytem, there are a couple of options: Either make sure it works regardless how it is instantiated, and/or make sure the parameters it needs to mess with the rest of the system are hidden and not readily available. There may be other options.

5
  • isn't the purpose of a singleton simply to "Just create one instance in some central place" (and also does so via lazy loading)?
    – Peter M
    Commented May 13, 2021 at 13:05
  • I agree that in typical desktop and server development the Singleton pattern is almost never useful. But e.g. when working with hardware/low level code I think it is well suited. E.g. you only have one motor connected to a microcontroller. In that microcontrollers code there is no use for more than one instance of a controller class for that motor. You don't want two to accidentally have two instances sending conflicting commands, leading to damage to physical things. So I wouldnt paint it this black-and-white
    – marstato
    Commented May 13, 2021 at 13:35
  • @PeterM My wording was maybe a bit imprecise. Singletons are looked up every time they are used. So while they are "at" a single place, or the code used to look it up is at a central place, the lookup/usage is not. Does that make more sense? Commented May 13, 2021 at 13:58
  • @marstato Even if you have a singleton motor controller, that doesn't really prevent you using the pins elsewhere, right? In my (hobby) arduino projects, I just declare all the hardware in one place, so I can see the pins I use at one glance. If you don't want to do that, you can always use some additional objects to manage the pins, make sure there are no conflicts, and require all hardware objects to get pins from that object. Commented May 13, 2021 at 14:04
  • @RobertBräutigam It's a trade off between a function call to get a pointer vs passing a pointer down through every function that might use it or need to pass it on to another function that will use it. The latter pollutes the function call hierarchy with irrelevant information. But the function call efficiency hit can be minimized by using an IoC approach in the classes that actually need to use the UI module.
    – Peter M
    Commented May 13, 2021 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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