Нужна помощь, чтобы избежать использования Singleton - PullRequest
9 голосов
/ 21 декабря 2011

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

Я разрабатываю приложение для кроссплатформенности (Windows XP / Vista / 7, Windows Mobile 6.x, Windows CE5, Windows CE6). В рамках этого процесса я реорганизую код в отдельные проекты, чтобы уменьшить дублирование кода и, следовательно, шанс исправить ошибки исходной системы.

Одна из таких частей приложения, которая создается отдельно, довольно проста, это менеджер профилей. Этот проект отвечает за хранение профилей. Он имеет класс Profile, который содержит некоторые данные конфигурации, которые используются всеми частями приложения. Он имеет класс ProfileManager, который содержит Profiles. ProfileManager будет считывать / сохранять Profiles в виде отдельных файлов XML на жестком диске и позволять приложению извлекать и устанавливать «активный» Profile. Простой.

В первой внутренней сборке графический интерфейс был анти-паттерном SmartGUI. Это была реализация WinForms без MVC / MVP, потому что мы хотели, чтобы она работала быстрее, а не была хорошо спроектирована. Это привело к тому, что ProfileManager был единственным. Это было так из любой точки приложения, графический интерфейс мог получить доступ к активной Profile.

Это означало, что я мог просто пойти ProfileManager.Instance.ActiveProfile, чтобы получить конфигурацию для различных частей системы по мере необходимости. Каждый GUI также может вносить изменения в профиль, поэтому у каждого GUI есть кнопка сохранения, поэтому у них всех также был доступ к методу ProfileManager.Instance.SaveActiveProfile().

Я не вижу ничего плохого в использовании синглтона здесь, и потому что я не вижу в этом ничего плохого, я знаю, что синглтоны не идеальны. Есть ли лучший способ, которым это должно обрабатываться? Должен ли экземпляр ProfileManager передаваться в каждый контроллер / презентатор? Когда создан ProfileManager, следует ли создавать другие основные компоненты и регистрироваться в событиях при изменении профилей. Пример довольно прост и, вероятно, является общей чертой во многих системах, поэтому думаю, что это отличное место, чтобы научиться избегать одиночных игр.

P.s. Мне нужно создать приложение на основе Compact Framework 3.5, который ограничивает множество обычных классов .Net Framework, которые можно использовать.

Ответы [ 3 ]

8 голосов
/ 22 декабря 2011

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

В случае вашего приложения у вас есть один «активный» профиль, который необходимо изменить в различных частях приложения. Я думаю, вам нужно решить, действительно ли профиль пользователя вписывается в эту абстракцию. Учитывая, что проявлением профиля является отдельный XML-файл на диске, я думаю, что это хорошо, если иметь один файл.

Я действительно думаю, что вы должны либо использовать внедрение зависимостей, либо шаблон фабрики, чтобы получить менеджер профилей. Вам нужно только написать модульный тест для класса, который требует использования профиля, чтобы понять необходимость этого; вы хотите иметь возможность передавать программно созданный профиль во время выполнения, иначе ваш код будет иметь тесно связанную зависимость с каким-либо файлом XML на диске где-либо.

5 голосов
/ 22 декабря 2011

Одна вещь, которую следует учитывать, - это иметь интерфейс для вашего ProfileManager и передавать его экземпляр конструктору каждого представления (или чего-либо еще), которое его использует.Таким образом, вы можете легко иметь синглтон или экземпляр для каждого потока / пользователя / и т. Д., Или иметь реализацию, которая обращается к базе данных / веб-службе / и т. Д.

Другой вариант - иметь всекоторые используют ProfileManager для вызова фабрики вместо прямого доступа к ней.Затем эта фабрика может вернуть экземпляр, опять же, это может быть одноэлементный файл или нет (перейти к базе данных, файлу, веб-службе и т. Д. И т. Д.), И большая часть кода не должна знать.

Не знает 't ответить на ваш прямой вопрос, но это делает изменение в будущем близко к нулю.

2 голосов
/ 22 декабря 2011

«Одиночки» действительно плохи, только если они используются для замены «глобальных» переменных. В этом случае, и если это то, для чего он используется, это не обязательно Синглтон в любом случае.

В случае, который вы описываете, это нормально и фактически идеально, так что ваше приложение может быть уверено, что Менеджер профилей доступен для всех, кто в нем нуждается, и что никакая другая часть приложения не может создать дополнительную, которая будет конфликт с существующим. Это также уменьшает уродливые дополнительные параметры / поля везде, где вы пытаетесь обойти один экземпляр, а затем сохраняете дополнительные ненужные ссылки на него. До тех пор, пока это происходит в одном-единственном экземпляре, я не вижу в этом ничего плохого.

Синглтон был разработан, чтобы избежать множественных экземпляров и единой точки «входа». Если это то, что вы хотите, то это путь. Просто убедитесь, что это хорошо задокументировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...