14

This is related to: What is so bad about Singletons

Can you give me some examples where Singletons can be avoided using other techniques? I need to use this in C++ so you can give examples with C++ specific techniques.

To be more clear: How you would implement a file manager, resource manager, log manager, etc without singletons.

Community
  • 1
  • 1
Mircea Ispas
  • 18,498
  • 26
  • 109
  • 202
  • 3
    Do you understand *why* they're bad? – GManNickG Sep 01 '11 at 07:13
  • 2
    Singletons aren't bad. Things like file managers and log managers are what singletons were made for. Using them for stuff they're not made for makes everyone think they're bad. –  Sep 01 '11 at 07:17
  • 2
    [Parameterize from above](http://accu.org/index.php/journals/1411) is usually the pattern to reach for when exterminating singletons. – CB Bailey Sep 01 '11 at 07:18
  • 2
    @bdares: A point of global access for a file or log manager is often a good thing. In my experience, not being able to have a second file or log manager isn't often an issue. All generalizations are false but "singletons are bad" is a pretty good one. IMHO. – CB Bailey Sep 01 '11 at 07:21
  • @Charles: You said `All generalizations are false but "singletons are bad" is a pretty good one.` Does it mean that *"singletons are bad"* is a `good` example of `false` generalization? :P – Nawaz Sep 01 '11 at 07:49
  • @Charles: Is PfA similar to Dependency Injection? That link read alternately as a bunch of clique-talk, and unfocused design speak, rather than a concrete definition. – Merlyn Morgan-Graham Sep 01 '11 at 07:58
  • 1
    @MerlynMorganGraham: They're not really the same thing. DI, as I understand it, is about removing the dependency of a function or class a the particular concrete type whereas PfA is much simpler, it's only about removing a function's or class' knowledge about how to access an object, instead receiving a reference to the object that it needs as a parameter. I though the article read quite well. Each to his own. – CB Bailey Sep 01 '11 at 08:07
  • 1
    @bdares: Those are good examples of where globally-accessible objects might be more convenient than objects passed by reference to everything that needs them. However, why would you also prevent me from creating my own independent instances of these things? That is the aspect of the Singleton antipattern that really makes no sense. – Mike Seymour Sep 01 '11 at 10:46
  • [Related](http://stackoverflow.com/questions/162042/are-there-any-viable-alternatives-to-the-gof-singleton-pattern) [Related](http://stackoverflow.com/questions/365261/ok-global-variable-is-condemned-singleton-is-despised-whats-the-alternative) [Related](http://stackoverflow.com/questions/5924763/c-getting-rid-of-singletons-alternative-to-functors-and-static-methods) [More Related](http://stackoverflow.com/search?q=alternative+singleton) – Rob Hruska Sep 01 '11 at 12:04
  • There is a nice article for singleton: https://www.michaelsafyan.com/tech/design/patterns/singleton – camino Jul 13 '17 at 19:41

3 Answers3

32

Simple: create a single instance of your file manager (or whatever) class, and then pass it around inside your application as necessary. Much will depend on your application structure, but typically you have some sort of controller object that creates the other important objects in the application. That might be the object to instantiate the file manager, and then pass it to the other objects it creates that need a file manager.

If you're using a singleton because there MUST be no more than one instance of a certain class, that's usually okay. If you're using it because a singleton is a globally-accessible object that lets you avoid thinking about how the other objects talk to each other and what each object is responsible for, that's where you start to run into problems.

The file manager is a nice example. At first it seems like there should only ever be zero or one instances of the file manager object. But is that necessary? Can't you have two file systems on one machine at the same time?

Caleb
  • 120,112
  • 19
  • 171
  • 259
6

How you would implement a file manager, resource manager, log manager, etc without singletons.

By not making them singletons and passing them down the call-tree and object-nets as parameters and references instead.

As a general rule: If you only need n instances, then create just n instances.

Or: If two instances of a well-designed class do not clash without breaking the class' contract, do not make it a singleton.

Sebastian Mach
  • 36,158
  • 4
  • 87
  • 126
3

Can you give me some examples where Singletons can be avoided using other techniques?

In higher level code, simply create the instance directly, and pass that around. You should be doing this at as high a level as possible that still makes sense.

In lower level code, accept a reference to an existing instance as a parameter. Don't accept a factory if you can avoid it without ham-stringing your design, and definitely don't call a constructor/new on things that aren't core to the logic of that class.

If you follow both these rules you'll implicitly manage the number of instances you create, and won't paint yourself into a corner by forcing a singleton design (that is often short-sighted to begin with).

How you would implement a file manager, resource manager, log manager, etc without singletons

I wouldn't. I'd create classes that could be instanced, and let the application itself call the shots on how many instances got created, and how they are created.

At the same time, I wouldn't let low level parts of my application call any shots. Just because I write to a log doesn't mean I have to know where it should be stored, what level of the logging hierarchy I'm writing to, what filters should be applied to it, etc.

I'd let the high level portions of my code decide these things. That way if I change my mind, I can scrap earlier decisions, blow away and recreate some top-level code, and not touch any of the code that writes to the log (the majority of my app).

Merlyn Morgan-Graham
  • 54,918
  • 14
  • 119
  • 174
  • I walked away from the keyboard, finished this up, and saw I was late to the game. It is mostly duplicate to what Caleb had to say. I'll leave it anyhow :) – Merlyn Morgan-Graham Sep 01 '11 at 07:59
  • And what happens when you're dealing with a concept that is fundamentally singleton? Do you have a bunch of objects floating around that are all just referring to the same internal data? – Nicol Bolas Sep 01 '11 at 10:16
  • 1
    @Nicol: No, you create the one instance and pass that around. I didn't mean to create instances that you don't need. However, I'm hard pressed to think of a concept that is fundamentally a singleton, once a suitable level of abstraction is adopted. The common examples: managers of all types, and print spoolers, simply aren't the Singletons they are reported to be. Just because you *want* only a single instance in an application doesn't mean a single instance is the only thing that makes sense. – Merlyn Morgan-Graham Sep 01 '11 at 16:43
  • @Merlyn: If it only makes sense to have 1 print spooler, for example, then it is a bad API that makes it possible to create more than one. And what good is an abstraction that allows you to create more than one, if each instance is just talking to the same stuff? The Zero, One or Infinity rule has _One_ in it for a reason. – Nicol Bolas Sep 01 '11 at 20:02
  • 1
    @Nicol: I disagree, but I shouldn't have gone this far. I forgot this his a holy war :) I'm bowing out now. – Merlyn Morgan-Graham Sep 01 '11 at 20:50
  • 1
    @Nicol: Then only make one. It's not like you accidentally make spoolers all the time, and who are you to say I don't have a use for two? – GManNickG Sep 01 '11 at 21:09