альтернатива синглтону в случае частого обращения

Очень часто одиночек плохая вещь (например, см. Вот а также Вот) и я хочу их избежать. Типичный вариант использования для одиночек У меня пока нет альтернативы, когда у вас есть несколько объектов, которые должны ссылаться на некоторый род / глобальный объект.

Пример 1У вас есть какое-то дерево, и каждый листовой объект должен знать корневой объект. (это плохой дизайн, но это только для примера)

Пример 2: у вас есть «глобальный» объект конфигурации, к которому обычно обращаются как global_config::get_instance()->get_item(name)

Вопрос: для приведенных примеров — есть ли альтернативные понятия одиночек кроме обширной передачи зависимостей и хранения для каждого экземпляра (иначе Dependancy Injection)?

2

Решение

Синглтоны решают только одно: «статический порядок инициализации фиаско» где глобальные объекты создаются в неопределенном порядке, поэтому они не могут зависеть друг от друга.

В противном случае синглтоны — это просто глобально доступные объекты, которые существуют только один раз.

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

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

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

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

2

Другие решения

Один подход, который я иногда нахожу полезным, состоит в том, чтобы позволить get_instance() метод для получения некоторого параметра и возврата различных объектов в зависимости от этого параметра, что-то вроде этого: global_config::get_instance(string serviceName), Если у вас есть несколько одноэлементных классов, вы можете использовать один и тот же параметр для получения каждого из них, поэтому каждый пользователь должен знать только один параметр, а не хранить ссылки на все синглтоны.

Для начала все звонки на get_instance() может возвращать один и тот же объект без учета аргумента, но если для разработки требуется, чтобы у вас были разные синглеты для разных частей приложения, вы можете адаптировать свой код так, чтобы разные части приложения передавали разные параметры get_instance(),

Более того, это также решит проблему тестирования вашего приложения, поскольку вы можете найти способ передать специальный параметр mock в get_instance() получить макет объекта.

Это может быть полезно для вашего global_cofig пример, но для вашего примера дерева вы должны обязательно сохранить ссылку на корень в листьях.

1

Вопрос: для приведенных примеров — есть ли альтернативные понятия одиночек кроме обширной передачи зависимостей и хранения для каждого экземпляра (иначе Dependency Injection)?

В обоих случаях вы говорите о видимость требование информации, ни единого (т.е. только один экземпляр объекта) требование.

Крейг Ларман «Применение UML и шаблонов» утверждает, что есть четыре способа, которыми объект может получить доступ к объекту В:

  • Атрибут видимости — B является атрибутом A.

  • Параметр видимости — B является параметром метода А.

  • Местная видимость — B (не параметрический) локальный объект в методе A.

  • Глобальная видимость — B в некотором роде виден во всем мире.

Последний — то, что обеспечено Синглтоном. Вот почему этот шаблон является спорным.

Внедрение зависимостей является первым вариантом — B вводится в A в своем конструкторе.

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

1
По вопросам рекламы [email protected]