Подтвердить что ты не робот

"Синглтон" заводы, хорошо или плохо?

У меня много (абстрактных) фабрик, и они обычно реализуются как одиночные.

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

В большинстве случаев мне нужно только принять решение при запуске, в котором реализация factory остальная часть программы кода, возможно, через некоторую конфигурацию

он выглядит, например. как

abstract class ColumnCalculationFactory { 
  private static ColumnCalculationFactory factory;

 public static void SetFactory(ColumnCalculationFactory f) {
         factory = f;
  }

  public static void Factory() {
         return factory;
  }

 public IPercentCalculation CreatePercentCalculation();
 public IAverageCalculation CreateAverageCalculation();
    ....

}

Состязаясь, обоняйтесь об этом, я просто не уверен, что - возможно, это более разобщенный глобальный, чем синглтон. Не похоже, что действительно действительно должен быть только один factory когда-либо создающий ColumnCalculations - хотя моим программам больше не нужно.

Считается ли это лучше всего? Должен ли я использовать их в каком-нибудь (полу) глобальном классе AppContext? Что-то еще (я не совсем готов переключиться на какой-то более крупный контейнер IoC, или spring.net еще совсем btw)?

4b9b3361

Ответ 1

Это действительно зависит от того, что вы делаете, и от объема вашего приложения. Если это просто небольшое приложение, и он никогда не будет расти за его пределами, тогда ваш нынешний подход может быть в порядке. Для этих вещей нет универсальной "лучшей" практики. Хотя я бы не рекомендовал использовать синглтоны для чего-либо другого, кроме методов без имени и/или односторонних вызовов (например, для ведения журнала), отбросив его из-под контроля "только потому, что" это односторонний подход не всегда подходит "./p >

Для чего-то другого, кроме тривиального или прототипного кода, мне лично нравится явно использовать инверсию управления с инсталляцией конструктора, так как это означает, что все зависимости учитываются, и вы не получаете никаких "сюрпризов". Компилятор не позволит вам создать экземпляр A без B и B без C. Синглтоны немедленно похоронят эти отношения - вы можете создать экземпляр A без B и B без C. Когда происходит вызов от A до B, вы получите нулевую ссылку исключение.

Это особенно раздражает при тестировании, поскольку вам приходится итеративно работать в обратном направлении через ошибки выполнения. Когда вы проверяете код, вы используете API так же, как это делает кодер-коллега, поэтому он указывает на проблемы с дизайном при таком подходе. Инъекция конструктора гарантирует, что этого никогда не произойдет - все зависимости указаны заранее. Недостатком с инсталляцией конструктора является то, что конфигурация графического объекта сложнее. Это смягчается с помощью контейнера IoC.

Я предполагаю, что я пытаюсь сказать, что если вы доберетесь до того, что собираетесь использовать какой-то объект контекста и шаблон реестра, вы также можете взглянуть на контейнеры IoC. Попытка скопировать вашу собственную версию mutt, вероятно, пустая трата времени, когда вы можете использовать установленный бесплатный продукт, такой как Autofac.

Ответ 2

Наличие нескольких синглтонов довольно типично и обычно не проблематично - многие одиночные пары приводят к некоторому раздражающему коду.

Мы только что пережили ситуацию, когда нам пришлось тестировать наши тяжелые однозарядные классы. Проблема в том, что когда вы тестируете класс b, и он получает класс c (singleton), вы не можете издеваться над классом c (по крайней мере EasyMock не позволит нам заменить статический метод factory одноэлементного класс.

Одно простое решение - иметь "сеттеры" для всех ваших синглтонов для целей тестирования. Не рекомендуется.

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

Помимо тестирования, я давно узнал, что когда никогда не будет больше одного экземпляра данного объекта; в следующем rev они часто хотят два, что делает синглтоны МНОГО лучше, чем статические классы - по крайней мере, вы можете добавить параметр в getter одноэлементного и вернуть второй без слишком большого количества рефакторинга (что опять-таки делает то, что делает DI).

Во всяком случае, посмотрите на DI, вы можете быть действительно счастливы.

Ответ 3

Нет, потому что вы здесь создаете глобальное состояние. Есть всевозможные проблемы с глобальным состоянием - главным из них, что одна функция зависит от довольно невидимого способа поведения других функций. Если функция вызывает другую функцию, которая забывает хранить и восстанавливать factory до ее завершения, возникает проблема, потому что вы даже не можете вернуть старое значение, если вы его где-то не сохранили. И вы должны добавить код, чтобы сделать это (судя по вашему коду, я бы предположил, что вы находитесь на языке с finally, что оставляет еще больше места для ошибок). Что еще, если вы закончите с кодом, который нужно быстро переключаться между двумя фабриками для двух подобъектов, вам нужно написать вызов метода в каждой точке - вы не можете сохранить состояние в каждом подобъекте (ну, вы можете, но затем вы побеждаете цель глобального состояния [что, по общему признанию, не так много)).

Вероятно, наиболее удобно хранить тип factory как член и передавать его конструктору новых объектов, которые в нем нуждаются (или создавать новый по мере необходимости и т.д.). Это также дает вам лучший контроль - вы можете гарантировать, что все объекты, построенные объектом A, прошли через тот же factory, или вы можете предложить методы для свопинга фабрик.

Ответ 4

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

Misko Hevery имеет хорошую статью об этом в своем блоге.

Ответ 5

Является ли это лучшей практикой?

Я не вижу проблемы: вы сказали, что "моим программам больше не нужно", поэтому реализация каких-либо более гибких/абстрактных может быть примером You Это не понадобится.

Ответ 6

Плохая форма singleton - это тот, который реализует эквивалент вашего метода Factory с помощью:

return new CalculationFactory ();

Это гораздо труднее заглушить, издеваться или обернуть.

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