Что альтернатива к Singleton

Использование функционального программирования / языки в рамках разработки ядра ОС.

112
задан John Mill 19 August 2009 в 15:21
поделиться

12 ответов

В блоге Google Testing есть серия записей об отказе от синглтона (для создания тестируемого кода). Может быть, это может вам помочь:

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

Короче говоря, мы перемещаем всех новых операторов на фабрику. Мы группируем все объекты с одинаковым сроком службы в одну фабрику.

127
ответ дан 24 November 2019 в 02:52
поделиться

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

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

15
ответ дан 24 November 2019 в 02:52
поделиться

Я мог бы сказать очевидное здесь, но есть ли причина, по которой вы не можете использовать структуру внедрения зависимостей, такую ​​как Spring или Guice ]? (Я считаю, что Spring теперь также доступен для .NET.)

Таким образом, фреймворк может содержать единственную копию объектов конфигурации, и вашим bean-компонентам (службам, DAO и т. Д.) Не нужно беспокоиться о ищу его.

Я обычно использую такой подход!

5
ответ дан 24 November 2019 в 02:52
поделиться

Если вы используете Spring Framework , вы можете просто создать обычный компонент. По умолчанию (или если вы явно установили scope = "singleton" ) создается только один экземпляр компонента, и этот экземпляр возвращается каждый раз, когда компонент используется в зависимости или извлекается через getBean ( ) .

Вы получаете преимущество единственного экземпляра без связывания паттерна Singleton.

4
ответ дан 24 November 2019 в 02:52
поделиться

Альтернатива - передать то, что вам нужно, вместо того, чтобы просить объект о вещах.

4
ответ дан 24 November 2019 в 02:52
поделиться

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

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

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

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

следует реорганизовать на:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

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

4
ответ дан 24 November 2019 в 02:52
поделиться

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

1
ответ дан 24 November 2019 в 02:52
поделиться

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

0
ответ дан 24 November 2019 в 02:52
поделиться

Зависит от того, какие инструменты / фреймворки и т. Д. Используются. С помощью инструментов внедрения зависимостей / ioc можно часто по-прежнему получить производительность / оптимизацию одноэлементного объекта, если контейнер di / ioc использует одноэлементное поведение для требуемого класса (например, интерфейс IConfigSettings), создав только один экземпляр класса. Это все еще может быть заменено для тестирования

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

0
ответ дан 24 November 2019 в 02:52
поделиться

Проверьте возможность настройки в качестве интерфейса обратного вызова. Таким образом, ваш чувствительный к конфигурации код будет выглядеть:

MyReuseCode.Configure(IConfiguration)

Код инициализации системы будет выглядеть:

Library.init(MyIConfigurationImpl)
0
ответ дан 24 November 2019 в 02:52
поделиться

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

0
ответ дан 24 November 2019 в 02:52
поделиться

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

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

вы можете вызвать createSingleton (Информация) непосредственно при запуске приложения (и в setUp-методах модульных тестов).

0
ответ дан 24 November 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: