PS C:\Users\Rack> systeminfo | findstr "System Memory"
System Boot Time: 5/5/2016, 11:10:41 PM
System Manufacturer: VMware, Inc.
System Model: VMware Virtual Platform
System Type: x64-based PC
System Directory: C:\Windows\system32
System Locale: en-us;English (United States)
Total Physical Memory: 40,959 MB
Available Physical Memory: 36,311 MB
Virtual Memory: Max Size: 45,054 MB
Virtual Memory: Available: 41,390 MB
Virtual Memory: In Use: 3,664 MB
По своей сути, Monostate - это просто синтаксический сахар вокруг Singleton. Monostate становится интересным, когда вы начинаете создание подклассов, потому что подклассы могут украшать разделяемое состояние другим поведением.
Простой - хотя и несколько надуманный и не очень эффективный :) - пример:
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();
}
}
А что, если мы хотим индексированный доступ?
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));
}
}
А как насчет отсортированных ключей?
public class SortedGlobalTable extends GlobalTable {
@Override
public Iterator <Key> iterator() {
return Collections
.unmodifiableSortedSet(new TreeSet<Key>(keySet())).iterator();
}
}
Каждый раз, когда вам нужно то или иное представление данных, вы просто создаете экземпляр соответствующего подкласса.
Конечно, действительно ли глобальные данные являются хорошей идеей в первое место - это другой вопрос, но по крайней мере Monostate дает вам больше гибкости в том, как вы его используете.
monostate and singleton are two faces of the same medal (global state):
i.e.:
Singleton singleton = Singleton.getInstance();
i.e.:
MonoState m1 = new MonoState();
MonoState m2 = new MonoState(); // same state of m1
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.
Кто-то должен просто заметить, что одиночные и моносостояния - чрезвычайно опасные паттерны. Обычно ими злоупотребляют ленивые программисты, которые не хотят думать о времени жизни объекта, который они хотят превратить в синглтон. Они усложняют тестирование и создают жестко связанные негибкие системы
. Крайне редко можно встретить ситуацию, когда действительно требуется синглтон или моностат. Предпочтительный метод взаимодействия объектов - внедрение зависимостей.
Об этом много написано: