Слишком много синглетонов в проекте - это плохая практика? - PullRequest
4 голосов
/ 09 декабря 2011

Почти в каждом проекте я создаю несколько классов, которые реализуют шаблон Singleton.Например, менеджер данных - если есть какая-то работа с файловой системой, загрузчик данных - если приложение подключается к Интернету, различные менеджеры ресурсов и т. Д. Иногда таких классов бывает до 5-7, и я начинаю чувствовать, что я делаючто-то не так.Плохо ли использовать слишком много паттернов Singleton?

Ответы [ 4 ]

4 голосов
/ 09 декабря 2011

Синглтоны не являются обязательно проблемами - наличие одного объекта, который является экспертом в своей области, может быть очень полезным, но явное кодирование одиночного объекта в объект почти всегда является плохой идеей (и частотоже плохо сделано).Оказывается, что лучше оставить конфигурацию приложения - включая решение о том, какие классы имеют одноэлементные экземпляры - отдельному слою, который специализируется на этом, например Spring for Java.Таким образом, уровень управления может следить за тем, что является одноэлементным, что является одноэлементным в конкретном контексте (например, в рамках сеанса), и что всегда необходимо создавать заново.Это дает вам возможность сосредоточиться на написании бизнес-логики.

В качестве примера того, почему одиночные пакеты могут быть проблемами и почему они должны быть одиночными по управлению / конфигурации, рассмотрим класс, который управляет подключением к базе данных.Классический чехол для синглтона можно сказать.Вы тоже будете правы, пока не обнаружите, что ваше приложение выросло до такой степени, что оно должно интегрировать соединения с двумя базами данных (это случается!), И тогда вам придется распутывать весь беспорядок.Если вы сохранили свой код независимо от того, имеет ли он дело с синглетами или нет, у вас есть прекрасная возможность справиться со всем этим, просто переконфигурировав;некоторые классы будут подключены к одной БД, а другие - к другой, но они просто будут с этим справляться с минимальными усилиями.(Все, что нуждается в обоих… ну, поэтому я сказал «отличный шанс».)

Еще один пример того, почему у Singletons могут быть проблемы, приходит, когда вы пишете тесты для своего кода.(Вы пишете тесты, да?) Явные синглтоны очень сложно тестировать, так как их сложно настроить и сложно изолировать.Вы не можете разорвать их между тестами, потому что это подразумевает, что их много.Если ваше приложение использует синглтоны только по конфигурации, конфигурация тестирования может легко изменить это, и вы можете выполнять свои тесты гораздо проще.

1 голос
/ 09 декабря 2011

С тех пор, как TDD занял свое место, программисты узнали, что тестирование синглетонов - это боль, и начали ее избегать. Тот же эффект может быть достигнут путем внедрения необходимых классов / ресурсов, таких как менеджер соединений, менеджер ресурсов и т. Д. Таким образом, в тестовой среде эти классы могут быть просто смоделированы, внедрены и покрыты тестом.

С другой стороны, в некоторых случаях использование синглтона кажется правильным - для обеспечения существования только одного экземпляра. То есть это полезно для пулов соединений, поскольку гарантирует, что один и только один экземпляр существует в то время и не будет утечек. (Примечание: не все реализации одноэлементного паттерна действительно могут обеспечить это. В Java правильным способом было бы использование enum - поскольку сам язык обеспечивает его уникальность.)

Итак, мой ответ - да, слишком много синглетонов - это плохо. Попробуйте вместо этого использовать принцип DI.

1 голос
/ 09 декабря 2011

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

В качестве примечания, JEE6, последняя версия Java Enterprise Edition, теперь включает поддержку для шаблона Singleton в качестве компонента EJB. Но подумайте немного, потребовалось шесть пересмотров стандарта, чтобы наконец это сделать!

0 голосов
/ 09 декабря 2011

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

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

Что-то вроде:

/**
 * Database manager for handling database related stuff
 * Does use Zend_Db and Zend_Config
 */
class Database_Manager
{
    protected static $dbos = array(); // Protected scope enforces encapsulation

    public static function getDbo($name)
    {
        // Init
        $hash = md5($name);

        // Attempt to use singleton     
        if (array_key_exists($hash, self::$dbos)) {
            return self::$dbos[$hash];
        }

        // Your db connection settings are set here either via
        // switch/case based on name, or loaded from a config file (yaml, xml, etc)
        $dbConnectionParams = array('your', 'connection', 'settings');

        $config = new Zend_Config($dbConnectionParams);

        $dbo = Zend_Db::factory($config->database);

        // Adding to singleton so can be referenced in future calls
        self::$dbos[$hash] = $dbo;

        return $dbo;
}

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

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

...