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.
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.