51

What are the scenarios when one would use a Monostate pattern instead of singleton inorder to maintain a global object?

Edit: I know what Singleton and Monostate patterns are. Have also implemented Singleton in quite a few scenarios. Just want to know the scenarios (case examples) where MonoState pattern needs to be implemented.

For eg. I need to maintain list of columns per screen in my windows forms app. I could use a Singleton Dictionary in this case. However, I am storing a List in the static global var and I wanted to provide indexers (since I need to dynamically add new entry to the list if key is not present) where I could specify ScreenDetails.ScreenName as a key & get the ScreenDetails.ColumnsTable. Since indexers can't operate on a static class I changed the pattern to Monostate.

So I would like to know which other scenarios may compel a user to use Monostate instead of Singletons.

SO User
  • 21,512
  • 16
  • 65
  • 108
  • 3
    See http://stackoverflow.com/questions/624653/is-monostate-the-good-cousin-of-the-evil-singleton among quite a few siomilar questions. –  May 20 '09 at 11:06
  • Yes, quite duplicated indeed: http://stackoverflow.com/questions/720744/static-class-and-singleton – cregox Nov 13 '13 at 20:44

5 Answers5

68

monostate and singleton are two faces of the same medal (global state):

  • monostate forces a behaviour (only one value along all class instances)
  • singleton forces a structural constraint (only one instance)

singleton usage is not transparent

i.e.:

Singleton singleton = Singleton.getInstance();

monostate usage is transparent

i.e.:

MonoState m1 = new MonoState();
MonoState m2 = new MonoState(); // same state of m1 
dfa
  • 107,531
  • 29
  • 184
  • 223
  • 2
    How is a singleton any less transparent? If I don't know that m1 is a monostate, I would just as clueless as if I didn't know what a singleton was. – Don Scott Nov 25 '14 at 00:53
  • 2
    @Don Scott -> monostate is transparent regarding how the clients use the monostate: `Users of a monostate do not behave differently than users of a regular object. The users do not need to know that the object is monostate`. In signleton pattern all the clients knows that they use a singleton, so the singleton is less transparent. – Cristian Bitoi May 17 '16 at 15:31
  • Curious that 'transparent' is so consistently used to describe monostate. Where the use of transparent for this pattern originate (in software lit.) ? It's clearly the opposite to the everyday use of the word, ex. 'The local government is completely transparent about contracting procedures'. Meaning anybody can see every part of the process. -- Now I scroll down to see the Martin quote!! – Stephan Luis Oct 16 '19 at 23:01
  • @StephanLuis The monostate pattern is transparent, because you don't see it's there, just like glass; whereas you see the singleton pattern is there, not just like glass. In your gov example, the gov is transparent because you 'see through' what it does; in this case you consider transparency as what it gives you access to, rather than transparency in istelf. – Maliafo Jan 21 '20 at 15:36
43

Here's what Robert C. Martin has to say about it: Singleton vs. Monostate (pdf)

SINGLETON is best used when you have an existing class that you want to constrain through derivation, and you don’t mind that everyone will have to call the instance() method to gain access. Monostate is best used when you want the singular nature of the class to be transparent to the users, or when you want to employ polymorphic derivatives of the single object.

ViRuSTriNiTy
  • 4,581
  • 1
  • 27
  • 52
egaga
  • 19,399
  • 10
  • 43
  • 58
21

At its base Monostate is just syntactic sugar around Singleton. Where Monostate gets interesting is when you start subclassing, because the subclasses can decorate the shared state with different behavior.

A simple -- if somewhat contrived and not very efficient :) -- example:

public class GlobalTable implements Iterable<Key> {

  /** Shared state -- private */    
  private static final Map<Key, Value> MAP = new LinkedHashMap<Key, Value>();

  /** Public final accessor */    
  public final Value get(Key key) {
    return MAP.get(key);
  }

  /** Public final accessor */    
  public final boolean put(Key key, Value value) {
    return MAP.put(key);
  }

  /** Protected final accessor -- subclasses can use this to access
      the internal shared state */    
  protected final Set<Key> keySet() {
    return MAP.keySet();
  }

  /** Virtual -- subclasses can override for different behavior */    
  public Iterator<Key> iterator() {
    return Collections.unmodifiableSet(MAP.keySet()).iterator();
  }
}

Now what if we want indexed access?

public class IndexedGlobalTable extends GlobalTable {

  public List<Key> getKeysAsList() {
    return Collections.unmodifiableList(new ArrayList<Key>(keySet()));
  }

  public Key getKeyAt(int index) {
    return getKeysAsList().get(index);
  }

  public Value getValueAt(int index) {
    return get(getKeyAt(index));
  }
}

How about sorted keys?

public class SortedGlobalTable extends GlobalTable {

  @Override
  public Iterator <Key> iterator() {
    return Collections
      .unmodifiableSortedSet(new TreeSet<Key>(keySet())).iterator();
  }

}

Any time you need one or the other view of the data, you just instantiate the appropriate subclass.

Of course, whether global data is really a good idea in the first place is another question, but at least Monostate gives you more flexibility in how you use it.

David Moles
  • 39,436
  • 24
  • 121
  • 210
  • “At its base Monostate is just syntactic sugar around Singleton.” Both are syntactic sugar around **global variables**. – Dúthomhas Mar 26 '19 at 22:52
  • @Dúthomhas I'd describe Singleton not as syntactic sugar around global variables but as a special case of a global variable, and only in the sense that all static fields are global variables. Strictly speaking I'd say Java doesn't even have global variables in the sense C or Ruby or Go has them, but if you think of Global Variable as a design pattern, then static fields are how Java implements that pattern and Singleton is a special case of it. – David Moles Apr 02 '21 at 17:34
10

Someone should just note that singletons and monostates are extremely dangerous patterns. They tend to get misused by lazy coders who don't want to have to think about the lifetime of the object they want to make into a singleton. They make testing more difficult and create inflexible systems that are tightly bound.

It's extremely rare to find a situation where a singleton or monostate is genuinely needed. The prefered method of object collaboration is Dependency Injection.

Lots has been written about this:

StackExchange123
  • 1,541
  • 5
  • 17
Ed Sykes
  • 1,289
  • 10
  • 17
  • 2
    +1 for being downvoted with "-1 for mentioning Dependency Injection" – mlvljr Feb 13 '14 at 13:02
  • I think it's only fair to note that spectre wrote their comment in '13. Things were different then; reflection could have been disqualifying, maybe they dealt with an implementation to be too long in the compile for rapid iteration; most of the solutions were pretty young, and did not always contribute to readability. These days, I'd point anyone looking for a good Java singleton to check out dagger 2's [application scope](https://guides.codepath.com/android/Dependency-Injection-with-Dagger-2#scopes) – anthropic android Aug 30 '16 at 04:36
3

The difference between the two patterns is one of behavior vs. structure. The SINGLETON pattern enforces the structure of singularity. It prevents any more than one instance from being created. Whereas MONOSTATE enforces the behavior of singularity without imposing structural constraints.

Benefits of the SINGLETON

  • Applicable to any class. You can change any class into a SINGLETON simply by making its constructors private and by adding the appropriate static functions and variable.
  • Can be created through derivation. Given a class, you can create a subclass that is a SINGLETON.
  • Lazy evaluation. If the SINGLETON is never used, it is never created.

Costs of the SINGLETON

  • Destruction is undefined. There is no good way to destroy or decommission a SINGLETON. If you add a decommission method that nulls out the instance, other modules in the system may still be holding a reference to the SINGLETON instance. Subsequent calls to Instance will cause another instance to be created, causing two concurrent instances to exist.

  • Not inherited. A class derived from a SINGLETON is not a singleton. If it needs to be a SINGLETON, the static function, and variable need to be added to it.

  • Efficiency. Each call to Instance invokes the if statement. For most of those calls, the if statement is useless.

  • Nontransparent. Users of a SINGLETON know that they are using a SINGLETON because they must invoke the Instance method.

Benefits of MONOSTATE

  • Transparency. Users of a MONOSTATE do not behave differently than users of a regular object. The users do not need to know that the object is MONOSTATE.

  • Derivability. Derivatives of a MONOSTATE are MONOSTATES. Indeed, all the derivatives of a MONOSTATE are part of the same MONOSTATE. They all share the same static variables.

  • Polymorphism. Since the methods of a MONOSTATE are not static, they can be overridden in a derivative. Thus different derivatives can offer different behavior over the same set of static variables.

  • Well-defined creation and destruction. The variables of a MONOSTATE, being static, have well-defined creation and destruction times.

Costs of MONOSTATE

  • No conversion. A normal class cannot be converted into a MONOSTATE class through derivation.

  • Efficiency. A MONOSTATE may go through many creations and destructions because it is a real object. These operations are often costly.

  • Presence. The variables of a MONOSTATE take up space, even if the MONOSTATE is never used.

Agile Software Development, Principles, Patterns, and Practices Robert C. Martin

Mohammad Akbari
  • 3,809
  • 5
  • 31
  • 58