Моностат против Синглтона - PullRequest
45 голосов
/ 20 мая 2009

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

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

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

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

Ответы [ 5 ]

67 голосов
/ 20 мая 2009

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

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

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

т.е:.

Singleton singleton = Singleton.getInstance();

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

т.е:.

MonoState m1 = new MonoState();
MonoState m2 = new MonoState(); // same state of m1 
41 голосов
/ 20 мая 2009

Вот что Роберт К. Мартин должен сказать по этому поводу: Синглтон против моностата (pdf)

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

17 голосов
/ 24 июля 2009

В своей основе Monostate - это просто синтаксический сахар вокруг Синглтона. 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 дает вам больше гибкости в их использовании.

8 голосов
/ 04 июня 2009

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

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

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

1 голос
/ 16 мая 2018

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

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

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

Стоимость SINGLETON

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

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

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

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

Преимущества МОНОСТАТА

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

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

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

  • Четко определенные создания и разрушения. Переменные МОНОСТАТА, будучи статичными, имеют четко определенные времена создания и уничтожения.

Расходы МОНОСТАТА

  • Без преобразования. Нормальный класс не может быть преобразован в МОНОСТАТ класс через деривацию.

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

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

гибкая разработка программного обеспечения, принципы, шаблоны и практики

...