MVK>Прочитал всю ветку. Адепты использования синглетонов — в частности впечатление таковых создают kuj и ArtDenis — в начаде своих рассуждений об удобоваримости синглетонов бездоказательно используют один тезис, который в общем случае неверен. Тезис таков: если объект должен быть только один — значит его разумно сделать в виде синглетона. Ни у одного из вышеупомянутых товарищей я так и не нашел развернутой защиты или доказательства этого тезиса, а ведь этот факт ой-как неочевиден. В качестве примера цитата kuj:
K>2) Приведите хотя бы пару примеров где РЕАЛЬНО помогает реализация данного паттерна?
MVK>Там, где гарантированно должен существовать только один экземпляр класса.
MVK>Бездумное взятие на вооружение таких вот утверждений и приводит к печальным последствиям.
Ничего не следует делать бездумно. Я уже об этом писал.
MVK>Это все тем более странно, что на вопрос "Как можно добиться единственности экземпляра класса?" обычно любой вменяемый программист способен привести несколько вариантов.
Приведите, будьте так любезны. А так же просьба объяснить чем именно эти варианты лучше паттерна Singleton.
MVK>P.S. Кстати, господа синглетонисты, по-вашему, какой вопрос имеет больший приоритет с точки зрения проектирования: MVK>В чьи обязанности будет входить создание экземпляра класса?
Некорректно поставленный вопрос.
MVK>или Какой способ выбрать, что добиться единственности экземпляра класса?
Паттерн Singleton.
Здравствуйте, Sni4ok, Вы писали:
S>но я лично по своему опыту знаю, что синглетоны очень часто юзабельны и без них просто никак.
Я луюбой код с синглетоном могу переписать без синглетона.
При этом он как правило становится проще (и никогда не становится сложнее) и всегда улучшается расширяемость и возможность повторного использования.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, kuj, Вы писали:
K>>1) В чем преимущество этого паттерна перед классом со статическими методами? kuj>В том, что не надо делать new.
Просто офигенное преимущество. Я плакал.
kuj>Примеры: много принтеров, но только один спуллер,
А ну-ну...
Сегодня один завтра понадобится два и привет... kuj>различные IoC контейнеры,
Вот уж где точно не место синглетонам. kuj>логгеры и т.д.
Очень часто нужно больше одного логгера.
kuj>Потому, что они не знают как и где его применять.
Во-во... я не знаю ни одного случая где снглетон дает преимущества но вот проблемы он создает ВСЕГДА!
Безвредны лишь именованные константы заданные во время компиляции.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
kuj>Приведите, будьте так любезны. А так же просьба объяснить чем именно эти варианты лучше паттерна Singleton.
Допустим, у нас есть некая реализация контейнера:
container.bind(MyInterface.class, new MyInterfaceMock());
Тем самым мы облегчим тестирование зависимых классов. Или даже так (переход от синглтона к неограниченному числу объектов):
container.bindFactory(MyInterface.class, new MyInterfaceFactory()); // на каждое обращение к get возвращает новый объект
Это опять же, неплохо при запуске набора тестов: можно смело корежить состояние объекта, потому что следующему тесту будет выдан новый.
Или скажем так:
ACL acl = ...
// создает один объект на нить, возвращает объект с контролем доступа в ACL
container.bind(MyInterface.class, new MyInterfaceFactory(), ThreadPolicy.LOCAL, acl);
Ну и т.д. Хотя самый простой способ заменить синглтон на что-то ещё — IoC.
Singleton.getInstance() -> private Singleton foo; getFoo(), setFoo()
А IoC-контейнер уже разберется, кому что раздать. Рефакторить такой код потом намного проще.
Здравствуйте, WolfHound, Вы писали:
K>>>1) В чем преимущество этого паттерна перед классом со статическими методами? kuj>>В том, что не надо делать new. WH>Просто офигенное преимущество. Я плакал.
Таки офигенное, т.к. не плодит лишние сущности, а следовательно экономит ресурсы системы.
kuj>>различные IoC контейнеры, WH>Вот уж где точно не место синглетонам.
Ну-ну.
kuj>>логгеры и т.д. WH>Очень часто нужно больше одного логгера.
Очень часто нужен именно один.
kuj>>Потому, что они не знают как и где его применять. WH>Во-во... я не знаю ни одного случая где снглетон дает преимущества но вот проблемы он создает ВСЕГДА!
Не знаете — ваши проблемы. В будущем может и узнаете. Не теряйте надежды.
Здравствуйте, Baudolino, Вы писали:
kuj>>Приведите, будьте так любезны. А так же просьба объяснить чем именно эти варианты лучше паттерна Singleton. B>Допустим, у нас есть некая реализация контейнера:
B>
Где гарантии, что Вася Пупкин за соседним компьютером не сделает MyInterface instance = new MyInterfaceSingleton() вместо
MyInterface instance = container.get(MyInterface.class)?
B>Хорошо тем, что потом можно написать так: B>
B>container.bind(MyInterface.class, new MyInterfaceMock());
B>
B>Тем самым мы облегчим тестирование зависимых классов. Или даже так (переход от синглтона к неограниченному числу объектов):
B>Ну и т.д. Хотя самый простой способ заменить синглтон на что-то ещё — IoC. B>Singleton.getInstance() -> private Singleton foo; getFoo(), setFoo() B>А IoC-контейнер уже разберется, кому что раздать. Рефакторить такой код потом намного проще.
Здравствуйте, kuj, Вы писали:
kuj>Таки офигенное, т.к. не плодит лишние сущности, а следовательно экономит ресурсы системы.
Какие еще ресурсы?
1 new это настолько малая величина что об этом даже разговаривать не стоит.
Это просто ничто.
kuj>Очень часто нужен именно один.
А ели выяснится что таки нужно два?
kuj>Не знаете — ваши проблемы. В будущем может и узнаете. Не теряйте надежды.
Ну хоть один пример можно?
Вы ведь знаете.
А если знаете то в чем проблема?
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
kuj>>Таки офигенное, т.к. не плодит лишние сущности, а следовательно экономит ресурсы системы. WH>Какие еще ресурсы? WH>1 new это настолько малая величина что об этом даже разговаривать не стоит. WH>Это просто ничто.
ну-ну.
kuj>>Очень часто нужен именно один. WH>А ели выяснится что таки нужно два?
Не выяснится.
kuj>Где гарантии, что Вася Пупкин за соседним компьютером не сделает MyInterface instance = new MyInterfaceSingleton() вместо kuj>MyInterface instance = container.get(MyInterface.class)?
Вася Пупкин за соседним компом может написать что угодно, но если у MyInterfaceSingleton видимость отличная от public, то код не скомпилируется.
Плюс ограничения системы безопасности на создание объектов (в Java).
kuj>Для mocking`а есть более удобные средства. kuj>
Здравствуйте, kuj, Вы писали:
kuj>Ничего не следует делать бездумно. Я уже об этом писал.
Отлично. Тогда можно привести аргументацию в защиту отквоченного мной в предыдущем посте тезиса?
kuj>Приведите, будьте так любезны. А так же просьба объяснить чем именно эти варианты лучше паттерна Singleton.
В начале топика есть пост IB, в котором он дал ссылку http://rsdn3.rsdn.ru/forum/message/2615563.1.aspx
. По этой ссылке ты найдешь всю интересующую тебя информацию. Если что непонятно — спрашивай.
MVK>>P.S. Кстати, господа синглетонисты, по-вашему, какой вопрос имеет больший приоритет с точки зрения проектирования: MVK>>В чьи обязанности будет входить создание экземпляра класса? kuj>Некорректно поставленный вопрос. MVK>>или Какой способ выбрать, что добиться единственности экземпляра класса? kuj>Паттерн Singleton.
Если внимательно прочитать мой пост, то станет ясно, что я не просил отвечать на вопросы. Т.к. очевидно, что однозначно ответить на эти вопросы невозможно, все зависит от ситуации(хотя второй ты просто-таки разделал под орех ). Я хотел подвести тебя к мысли, что решая одну задачу единственности экземпляра класса, синглетон автоматически навязывает программисту решение другой, а именно кто будет отвечать за создание экземпляра. А это совершенно разные аспекты и не хотелось бы их увязывать между собой. Иногда, конечно, получается удачно, как в примере с DBNull.Value приведенным Blondy, но увы только иногда. Собственно, все это следствие нарушения синглетоном SRP.
kuj>Где гарантии, что Вася Пупкин за соседним компьютером не сделает MyInterface instance = new MyInterfaceSingleton() вместо kuj>MyInterface instance = container.get(MyInterface.class)?
Контролировать такие вещи значительно проще, чем разгребать последствия синглетонов.
kuj>Для mocking`а есть более удобные средства. kuj>
Я думаю, тут все в курсе
А вот теперь расскажи нам, как ты будешь делать mock-объект для PrinterSpoolerSingleton с помощью того-же RhinoMocks, если тебе надо написать тесты для MyClass?
public class MyClass
{
public void DoSomething()
{
...
PrinterSpoolerSingleton.Print();
...
}
}
kuj>И в чем причина штанов, полных радости? Узнали нечто новое для себя?
Нет, конечно. Дело в том, что я не писал о средствах создания моки и был несколько удивлен тем, что вы так круто перевели разговор на эту тему. Простите, вырвалось. Не в средствах дело, а в том, как подружить моки с синглтонами. Пример ниже вам привели.
Здравствуйте, MaximVK, Вы писали:
MVK>Если внимательно прочитать мой пост, то станет ясно, что я не просил отвечать на вопросы. Т.к. очевидно, что однозначно ответить на эти вопросы невозможно, все зависит от ситуации(хотя второй ты просто-таки разделал под орех ). Я хотел подвести тебя к мысли, что решая одну задачу единственности экземпляра класса, синглетон автоматически навязывает программисту решение другой, а именно кто будет отвечать за создание экземпляра. А это совершенно разные аспекты и не хотелось бы их увязывать между собой. Иногда, конечно, получается удачно, как в примере с DBNull.Value приведенным Blondy, но увы только иногда. Собственно, все это следствие нарушения синглетоном SRP.
На самом деле это не так, достаточно в классе синглетона иметь методы CreateInstance/DestroyInstance и GetInstance. CreateInstance вызывается логическим владельцем синглетона, а GetInstance всеми остальными клиентами. При этом клиент должен быть готов, что GetInstance может провалиться, хотя на практике это обозначает, что объект-синглетон создается/уничтожается в неправильном месте. Это же позволяет решить тонкие проблемы с доступом из разных потоков — CreateInstance вызывается до создания первого рабочего потока, а DestroyInstance — после удаления последнего. В качестве синглетонов у меня обычно оформляются фасады подсистем. Например, очень хорошо срабатывает это в случае System Layer.
Здравствуйте, WolfHound, Вы писали:
kuj>>Очень часто нужен именно один. WH>А ели выяснится что таки нужно два?
Надоели невнимательные читатели, которые приводят это как недостаток синглтона... "А если таки надо 2-а", то открываем Паттерны от GOF и читаем как сделать singleton, который контролирует число отличное от 1(изменения незначительны). Побеждайте лень.
Здравствуйте, John Grey, Вы писали:
JG>Надоели невнимательные читатели, которые приводят это как недостаток синглтона... "А если таки надо 2-а", то открываем Паттерны от GOF и читаем как сделать singleton, который контролирует число отличное от 1(изменения незначительны). Побеждайте лень.
Когда я говорю 2 логгера я говорю не два объекта, а два разных логгера. С разными настройками, с разным уровнем логгирования, с разными файликами куда все пишется,...
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, John Grey, Вы писали:
JG>>Надоели невнимательные читатели, которые приводят это как недостаток синглтона... "А если таки надо 2-а", то открываем Паттерны от GOF и читаем как сделать singleton, который контролирует число отличное от 1(изменения незначительны). Побеждайте лень. WH>Когда я говорю 2 логгера я говорю не два объекта, а два разных логгера. С разными настройками, с разным уровнем логгирования, с разными файликами куда все пишется,...
Угу... А что мешает различия положить стратегии и инициализировать логеры разными стратегиями(общий то интерфейс один)?
А говоря по сути синглтон это шаблон контроля количества объектов одного типа в системе, а предоставление доступа отовсюду к этим объектам уже дополниельная фишка, которую каждый может использовать по желанию, а может и не использовать если руки прямые и головы хватает на переосмысление идей других людей.
Здравствуйте, John Grey, Вы писали:
JG>Угу... А что мешает различия положить стратегии и инициализировать логеры разными стратегиями(общий то интерфейс один)?
А нафига мне этот геморой если я просто в конфиге прописываю что-то типа
И все!
Дальше просто запрашиваю компонент по имени и кастую к интерфейсу.
JG>А говоря по сути синглтон это шаблон контроля количества объектов одного типа в системе, а предоставление доступа отовсюду к этим объектам уже дополниельная фишка, которую каждый может использовать по желанию, а может и не использовать если руки прямые и головы хватает на переосмысление идей других людей.
А накой черт это все вобще надо?
Какую задачу это решает?
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, COFF, Вы писали:
COF>Так а запрашиваете-то у кого? Или сам контейнер должен быть оформлен в виде синглетона, или его надо тянуть через все приложение.
Протащить контекст гораздо проще и дешевле чем разбиратся с теми макаронами что случаются из-за применения синглетонов.
Просто решение само по себе получается гораздо болие гибким.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн