Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid singletons when making an OOP state machine design?

I'm in the midst of trying to teach myself programming. I started the same way that I'm sure most people start; making small, messy apps and games that do simple things in not-so-simple ways. Recently, I've been trying to take the next step by writing a slightly more complex game that uses OOP design to write better, more modular code!

The main issue I've been having is the design of my main StateManager (FSM) class (to switch between intro/menu/game/etc screen states). I've looked high and low, and I've only really seen two methods of designing them:

  • Use a switch/case statement + an enum to switch between states..

  • Make a singleton FSM class that handles pushing/popping states to/from a vector..

Now, my problem is, the switch case statement is very repetitive and clunky, and it kind of works against my goal of using this project to teach myself OOP.

My second, and bigger problem is the 'singleton' suggestion.

As I said before, I'm trying to teach myself, and I still have a lot to learn when it comes to programming, especially in the field of OOP and design patterns and all that stuff. I've run into an issue where, for EVERY single 'singletons are evil' thread and discussion that I find, I find just as many tutorials and references where people use singletons in their code to make 'engine' classes and FSMs. It's a very consistent mixed message.

I suppose I just don't understand why... Even if you only want/intend to have a single object of a class, why is it necessary/beneficial to make the constructor private and create a singleton? I've read a lot about how singletons are bad, how they are essentially global, how they get in the way of multi-threading, and how many programmers consider them overused or just plain bad design... Yet I see example after example of people using them, and very few counter examples showing alternate methods.

Couldn't the same type of thing be done with just a regular class? What's the purpose of explicitly restricting the creation of instances? I've heard only negative things about singletons, yet people seem to use them constantly... Am I completely missing something about singletons and OOP?

Is the use of singletons just a trend, or is it just a trend when people call singletons 'evil'? How do I get around this..? Isn't there something between the switch/case FSM and the singleton FSM?? Couldn't someone design their program's state system the exact same way without making any of their classes singletons? Would that change something? [confused]

like image 520
MrKatSwordfish Avatar asked Aug 09 '12 11:08

MrKatSwordfish


People also ask

How can Singleton be prevented?

Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose you serialize an object of a singleton class. Then if you de-serialize that object it will create a new instance and hence break the singleton pattern.

Why should you avoid singletons?

The most important drawback of the singleton pattern is sacrificing transparency for convenience. Consider the earlier example. Over time, you lose track of the objects that access the user object and, more importantly, the objects that modify its properties.

How do I get rid of Singleton?

Getting rid of a singleton is extremely easy: create an abstraction and depend on that instead of the concrete Singleton. Once this is done, you'll have to decide if you want to fix all the callers of your class or if you only want to do this locally because you don't have time for that or there are to many callers.

What is the alternative to Singleton?

Static singleton void method could be replaced with: Dependency. Resolve<IFoo>(). DoSomething();


2 Answers

Couldn't the same type of thing be done with just a regular class? What's the purpose of explicitly restricting the creation of instances? I've heard only negative things about singletons, yet people seem to use them constantly... Am I completely missing something about singletons and OOP?

No, I believe you're on the right track: there's absolutely no reason to prevent the creation of two instances. The Universe won't implode because of that.

It's a completely unnecessary restriction. Since you have to manually code that restriction, it's quite silly to have it at all (if you had to write code to lift it, that would be another matter).

I suppose there may be weird and rare situations where the Universe does implode if a second instance is created, but that sounds quite farfetched. In any case, it doesn't justify the prevalence of singletons all over the Internet.

I can't really explain why people use them constantly without insulting the reasoning abilities of those people, so I will refrain from doing so.

Couldn't someone design their program's state system the exact same way without making any of their classes singletons? Would that change something?

The only thing it changes is that by making it a singleton you prevent yourself from creating throwaway instances for unit testing. Everything else just works the same.

like image 113
R. Martinho Fernandes Avatar answered Sep 22 '22 12:09

R. Martinho Fernandes


As is often the case, there is no one simple answer. In C++, the singleton pattern also manages order of initialization issues, which are important if it is to be used in the constructors of static objects. And there are certain types of objects where multiple instances can only be a programming error; if you can prevent them, why not.

On the other hand, I have a great deal of difficulty imagining a case where a StateManager class should be a singleton. It is in no way managing some unique resource, or some meta-functionality (e.g. like logging) which by its very nature must be unique. And I can't imagine it being used in the constructors of static objects either.

A statement such as "singletons are bad" is very misleading; for some things, they are the most appropriate solution. But just because they aren't bad in the absolute doesn't mean that they are appropriate everywhere. They solve one particular, very limited problem. When you need to solve that problem, not using a singleton is bad. But (as is true for just about everything), using it when it isn't appropriate is bad.

like image 22
James Kanze Avatar answered Sep 20 '22 12:09

James Kanze