Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

This question already has an answer here:

Is it necessarily a bad thing to use a singleton for a sound manager?

I am having a really tough time determining whether or not I should go ahead and use a singleton (which is easy/it works) or if I am shooting myself in the foot by deviating away from good OOP principles (since a singleton is basically a glorified single-instance global variable of sorts).

share|improve this question
add comment

marked as duplicate by bummzack, Josh Petrie, Byte56, Trevor Powell, Anko Apr 7 '13 at 16:32

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2 Answers

An Interface is more suitable for a sound manager as a singleton can be too restrictive and should be used sparingly; otherwise you run the risk of introducing a global state within your application. As you stated, a singleton is "basically a glorified single-instance global variable" and in some circles, considered an anti-pattern. Singletons are not necessarily 'bad' per se; however, if a more suitable solution exists, use it (the more suitable solution, that is).

share|improve this answer
add comment

While Singleton pattern can be dangerous, there is cases when it's simply more efficient and actually makes sense, in case of sound – absolute majority of devices capable of playing games have single sound output. But even then I would suggest using it's cousin – Multiton pattern. You can check SharedObject class in ActionScript to see one of examples, it uses SharedObject.getLocal(<someIdentifier>) and creates instances when it's needed.

An advantage is that it gives you more flexibility, consider following example:

class SoundManagerFactory {
  private const managers:Dictionary = new Dictionary();

  public function getManager(id:Object = 'default'):ISoundManager {
    if (managers[id] == null) {
      managers[id] = new SoundManager();
    }
    return managers[id];
  }
}
interface ISoundManager {}
class SoundManager implements ISoundManager {}

// Usage
SoundManagerFactory.getManager(); //default manager, works just like singleton

In this case, if at some point you decide to break your functionality to say Ambient, Voice, Music, Effects (Pretty common for video games to have separate volume controls for different types of sound).

SoundManagerFactory.getManager('ambient');
SoundManagerFactory.getManager('music');
SoundManagerFactory.getManager('effects');

And of course, breaking factory apart from singleton pattern allows you to easily use polyphormism to create sound managers that might have different implementation detail if needed.

public function getManager(id:Object = 'default'):ISoundManager {
  if (managers[id] == null) {
    managers[id] = createManager(id);
  }
  return managers[id];
}

public function createManager(id):ISoundManager {
  if (id == 'something') {
    return new DefaultSoundManager();
  } else {
    return new StreamingSoundManagerWithLasersAndBlackjack();
  }
}
share|improve this answer
add comment

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