Моностат против Синглтона

Каковы сценарии, когда вы используете шаблон Monostate вместо singleton inorder для поддержки глобального объекта?

Изменить: я знаю, что представляют собой шаблоны Singleton и Monostate. Также реализовали Singleton в довольно многих сценариях. Просто хочу знать сценарии (примеры), где должен быть реализован шаблон MonoState.

Напр. Мне нужно вести список столбцов на экран в приложении Windows Forms. В этом случае я мог бы использовать словарь Синглтона. Тем не менее, я сохраняю List в статическом глобальном var, и я хотел бы предоставить индексаторы (так как мне нужно динамически добавлять новую запись в список, если нет ключа), где я мог бы указать ScreenDetails.ScreenName как ключ и получить ScreenDetails .ColumnsTable. Поскольку индексы не могут работать в статическом classе, я изменил шаблон на Monostate.

Поэтому я хотел бы знать, какие другие сценарии могут заставить пользователя использовать Monostate вместо Singletons.

На его основе Monostate является синтаксическим сахаром вокруг Синглтона. Когда Monostate становится интересным, это когда вы начинаете подclassу, потому что подclassы могут украшать разделяемое состояние с другим поведением.

Простой – если несколько надуманный и не очень эффективный 🙂 – пример:

public class GlobalTable implements Iterable { /** Shared state -- private */ private static final Map MAP = new LinkedHashMap(); /** 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 keySet() { return MAP.keySet(); } /** Virtual -- subclasses can override for different behavior */ public Iterator iterator() { return Collections.unmodifiableSet(MAP.keySet()).iterator(); } } 

Теперь, что, если мы хотим индексированный доступ?

 public class IndexedGlobalTable extends GlobalTable { public List getKeysAsList() { return Collections.unmodifiableList(new ArrayList(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  iterator() { return Collections .unmodifiableSortedSet(new TreeSet(keySet())).iterator(); } } 

Каждый раз, когда вам нужно одно или другое представление данных, вы просто создаете соответствующий подclass.

Конечно, действительно ли глобальные данные действительно являются хорошей идеей, в первую очередь, это другой вопрос, но, по крайней мере, Monostate дает вам больше гибкости в том, как вы его используете.

monostate и singleton – две грани одной и той же медали (глобальное состояние):

  • monostate заставляет поведение (только одно значение по всем экземплярам classа)
  • singleton заставляет структурное ограничение (только один экземпляр)

использование singleton не прозрачно

то есть:

 Singleton singleton = Singleton.getInstance(); 

использование monoстата прозрачно

то есть:

 MonoState m1 = new MonoState(); MonoState m2 = new MonoState(); // same state of m1 

Вот что Роберт К. Мартин должен сказать об этом: Singleton vs. Monostate (pdf)

SINGLETON лучше всего использовать, когда у вас есть существующий class, который вы хотите ограничить с помощью деривации, и вы не возражаете, чтобы каждый получил вызов метода instance () для получения доступа. Моностат лучше всего использовать, когда вы хотите, чтобы исключительная природа classа была прозрачной для пользователей или когда вы хотите использовать полиморфные производные одного объекта.

Кто-то должен просто отметить, что одиночные и monoпольные являются экстремально опасными образцами. Они, как правило, злоупотребляют ленивыми кодировщиками, которые не хотят думать о жизни объекта, который они хотят сделать, в одноэлемент. Они затрудняют тестирование и создают негибкие системы, которые тесно связаны.

Очень редко можно найти ситуацию, когда одиночный или monoстатный действительно необходим. Предпочтительным методом совместной работы объектов является инжекция зависимостей.

Об этом написано много:

  • accu singleton anti-pattern article
  • шотландские денсмор на синглонах, являющихся злыми
  • перегрузка стека о одиночных

Различие между двумя шаблонами – это поведение и структура. Шаблон SINGLETON обеспечивает структуру сингулярности. Это предотвращает создание нескольких экземпляров. В то время как MONOSTATE применяет поведение сингулярности без наложения структурных ограничений.

Преимущества SINGLETON

  • Применимо к любому classу. Вы можете изменить любой class в SINGLETON, просто сделав его конструкторы частными и добавив соответствующие статические функции и переменную.
  • Может быть создано путем деривации. Учитывая class, вы можете создать подclass, который является SINGLETON.
  • Ленькая оценка. Если SINGLETON никогда не используется, он никогда не создается.

Расходы SINGLETON

  • Уничтожение не определено. Нет хорошего способа уничтожить или вывести из строя СИНГЛЕТОН. Если вы добавите метод декомпозиции, который завершит удаление экземпляра, другие модули в системе все еще могут содержать ссылку на экземпляр SINGLETON. Последующие вызовы экземпляра вызовут создание другого экземпляра, в результате чего будут существовать два параллельных экземпляра.

  • Не унаследовано. Класс, полученный из SINGLETON, не является ничем. Если это должен быть SINGLETON, статическая функция и переменная должны быть добавлены к ней.

  • Эффективность. Каждый вызов экземпляра вызывает оператор if. Для большинства этих вызовов оператор if бесполезен.

  • Непрозрачные. Пользователи SINGLETON знают, что они используют SINGLETON, потому что они должны вызывать метод Instance.

Преимущества MONOSTATE

  • Прозрачность. Пользователи MONOSTATE не ведут себя иначе, чем пользователи обычного объекта. Пользователям не нужно знать, что объект MONOSTATE.

  • Порождаемость. Производные MONOSTATE являются MONOSTATES. Действительно, все производные MONOSTATE являются частью одного и того же MONOSTATE. Все они имеют одни и те же статические переменные.

  • Полиморфизм. Поскольку методы MONOSTATE не являются статическими, их можно переопределить в производном. Таким образом, различные производные могут предлагать разные виды поведения по одному и тому же набору статических переменных.

  • Четкое создание и уничтожение. Переменные MONOSTATE, являющиеся статическими, имеют четко определенные времена создания и уничтожения.

Стоимость MONOSTATE

  • Нет конверсии. Обычный class не может быть преобразован в class MONOSTATE через деривацию.

  • Эффективность. MONOSTATE может пройти через многие творения и разрушения, потому что это реальный объект. Эти операции часто являются дорогостоящими.

  • Присутствие. Переменные MONOSTATE занимают место, даже если MONOSTATE никогда не используется.

Разработка гибких программных продуктов, принципы, шаблоны и практика Роберт К. Мартин

  • Использование инъекции зависимостей без какой-либо библиотеки DI
  • Разница между статическим classом и одноэлементным шаблоном?
  • Лучший способ использования StructureMap для реализации шаблона страtagsи
  • Лучший способ управлять ProgressDialog из AsyncTask
  • Что такое инъекция зависимости?
  • Как автоматически регистрировать class при создании
  • Почему я должен изолировать объекты домена от своего уровня представления?
  • Является ли ServiceLocator анти-шаблоном?
  • UI Design Pattern для Windows Forms (например, MVVM для WPF)
  • Можете ли вы объяснить шаблон дизайна контекста?
  • Синглтон, поясняющий Джон Скит
  • Давайте будем гением компьютера.