Singleton - зло?
Сам обильно их не использовал, на памяти только один раз - и тот чисто для практики. Проект расширять не пришлось, поэтому проблем и не было. А вообще, я сам отрицательно отношусь к сему шаблону и хотелось бы узнать чужое мнение и опыт по этому вопросу...
p.s. недавно на этом форуме Green написал статейку по тому как с ними бороться
почему вы так считаете?
Может, повезет и система не будет нуждаться в расширении в этом направлении, а может не повезти... :)
Суть синглтона - защитить пользователя системы от ошибки создания объектов, которые могут существовать в единственном экземпляре. Т.е. в принципе, если проектируем правильно, синглтон и не нужен. С другой стороны, защита такого рода приводит к другой проблеме - глобализация данных. Что хуже, ещё нужно подумать.
Можно обеспечить существование единственного экземпляра и другими, менее жестокими способами, например, с помощью фабрики объектов. Синглтон содержит в себе фабрику единственного экземпляра, а так получается, мы выворачиваем синглтон наизнанку: теперь фабрика содержит экземпляр, а уж единственный он или нет - ей решать.
Это (IMHO) более гибкий способ, т.к. в зависимости от ситуации и с развитием системы, фабрика может создавать или не создавать новые экземпляры, а кроме того исключается "глобализация", система теперь "не знает" с единственным она работает экземпляром или нет, этим заведует лишь фабрика.
Резюме:
1) при развитии системы с синглтонами могут возникнуть проблемы,
2) без синглтонов можно обойтись, заменив их другим решением (фабрика)
Вывод: синглтоны - скорее зло, чем добро.
Сначала решил, что класс действительно может иметь единственный экземпляр, но не это меня сподвигнуло на его использование, а банальная лень передачи указателя/ссылки :) и использование глобальных переменных - далеко не мудрое решение
Это (IMHO) более гибкий способ, т.к. в зависимости от ситуации и с развитием системы, фабрика может создавать или не создавать новые экземпляры,
Ето конечно более гибкий способ, но вот что меня интересует. Если система в начале думает что она одна и достает етот екземпляр (который деюре не синглетон но дефакто таки один) из фабрики то что есть фабрика ? Как она должна гарантировать то что наш екземпляр будет един на нашу немасштабированую систему без того же приема что и в синглетоне ?. Ну припустим ето нас не очень пока интересует. Варианты есть. Смасштабируем - поменяем фабрику.
Но я так полагаю что методу фабрики который возвращает екземпляр параметры не передаются ? ведь зачем они если мы понятия не имеем будет ли система масштабироваться.
Как фабрика без параметров узнает из какой смасштабированой системы (ну уже подсистемы) у нее екземпляр просят ?
ЗЫ. Еще один вопрос родился.
Если так подходить к делу то получается что любое статическое поле не являющееся константой ето во много раз хуже синглетона ???
С точки зрения возможности розмножения системы я полностю с етим согласен, но помойму раз уж чтото что не плановалось масштабировать масштабируется, значит или сразу не подумали, либо заказчику ух как захотелось. И если дело в заказчике то не грех переделать затратив больше труда и взяв больше денег, А сразу мучится и пытаься предвидеть все наперед ..... больше сам себе проблем наделаеш. Возможно я просто не понимаю как можно легко обойтись без синглетонов с помощю фабрик ?
.....
[QUOTE=Эдсгер Дейкстра;]Инструменты, которые мы применяем, оказывают глубокое (и тонкое) влияние на наши способы мышления и следовательно на нашу способность мыслить. [/QUOTE]
Но я так полагаю что методу фабрики который возвращает екземпляр параметры не передаются ? ведь зачем они если мы понятия не имеем будет ли система масштабироваться.
Как фабрика без параметров узнает из какой смасштабированой системы (ну уже подсистемы) у нее екземпляр просят ?
Ты же сам ответил на свой вопрос:
"Варианты есть. Смасштабируем - поменяем фабрику."
Как вариант, введем параметр у фабрики.
ЗЫ. Еще один вопрос родился.
Если так подходить к делу то получается что любое статическое поле не являющееся константой ето во много раз хуже синглетона ???
С точки зрения возможности розмножения системы я полностю с етим согласен, но помойму раз уж чтото что не плановалось масштабировать масштабируется, значит или сразу не подумали, либо заказчику ух как захотелось. И если дело в заказчике то не грех переделать затратив больше труда и взяв больше денег, А сразу мучится и пытаься предвидеть все наперед ..... больше сам себе проблем наделаеш.
Интересные у вас заказчики, говорят использовать или нет синглтоны и т.п. :D
Заказчик обычно говорит: "хочу красиво", а что там внутри его не интересует.
Заказчик обычно ищет, где выгоднее (обратите внимание: не "где дешевле", а "где выгоднее", разница существенная). Поэтому команда должна быть конкурентноспособной, а значит и её наработки, и стиль, и каждый программист в отдельности должны быть конкурентноспособными (эффективными).
На счет "сразу не продумали", цитирую:
Т.к. вся система изначально могла в приложении существовать только в единственном экземпляре, то сама она и многие её подсистемы были сделаны синглтонами ("одиночками"), кроме того в системе существует множество глобальных объектов.
За время своего существования (около 10 лет) система обросла множеством таких подсистем и глобальных объектов. И вот в один прекрасный момент понадобилось создать несколько таких систем в одном приложении. Вот тогда и почувствовалось всё зло от глобальных данных и синглтонов.
Последовательный рефакторинг (избавление от "одиночества") всех подсистем оказался очень трудоемким, в частности из-за большой связанности подсистем: приходилось протаскивать ссылки на соседние подсистемы по всей иерархии вызовов и/или хранить множество перекрестных ссылок.
Сразу мучаться и не надо, отсюда и возникает вопрос: зло синглтоны или нет. Если сразу понимаешь, что зло, то стараешься избежать их использования, и не надо ничего предвидеть. Это и называется стиль, когда не "предвидишь" в данном конкретном случае, а пользуешься набором правил выработанных или приобретенных.
"Не совать пальцы в розетку", и не надо предвидеть есть там напряжение или нет.
"Не направлять оружие на людей", и не надо предвидеть будет оно заряжено или нет.
Возможно я просто не понимаю как можно легко обойтись без синглетонов с помощю фабрик ?
Возможно. Но это лишь один из примеров.
Но опять же если роботу отдать и забыть - то почему бы их не использовать. Конечно если проект серезный - ты 100% прав в том чтоб ими не пользоваться.
Но я бы избавлялся от них не с помощю фабрик. Не нравится мне такой выход. Если я планирую что система будет розвиватся и совсем непонятно как то я бы сделал саму систему сущностю.
Пусть она поддерживает некий интерфейс IRunable и все что в ней должно быть глобальным пускай содержится в етой сущности. Подсистемы етой системы, использующие глобальный ресурс (ну типа синглетоны, статические поля и прочие глобальные переменные) должны хранить ссилку на инстант нашей системы сущности, чтоб получить доступ к общему ресурсу.
Реально глобальной я би сделал только одну самую начальную сущность (к примеру клас со статическим методом, чтото типа public static main), которая будет запускать мою IRunable. Если придется масштабировать или достраивать поверха вверх - просто делаем новий IRunable верхнего уровня, который в себе уже запускает прежние IRunable в сколь-угодном количестве и переделываем наш клас со статической функцией который ету всю кухню запускает.
Конечно предложеную мною сущность системы можно асоциировать с фабрикой - но помоему ето разные вещи. Ето получится не фабрика, а держатель псеглобальных переменных. И не очень напряжет при розроботке первичной системы. Но ето только моя теория. Практически я таког не делал.
ЗЫ. не смотря на то что я сказал "синглетоны не очень хорошо" - проблема не в синглетоне, а в том что мы не можем нормально определится что должно быть глобально а что нет и тыкаем етот паттерн всюду где не надо. Так что я голосую за добро, но теперь буду с етим добром намного осторожнее. :)
ИМХО. На счет розвития системы на протяжении 10 лет - ну дык срок то немалый - тут и проблем с рефакторингом стыдится нельзя. И возможно использование одиночек в том случае было вполне оправдано и выгодно (но ето тебе виднее, ты видел как сделано и ты переделывал).
ЗЫЫ. Подозреваю что хранение ссылок на инстанс системы-сущности может вызват неудобства при роботе сборщика мусора. Но таких проблем и без меня хватит. Я вообще не понимаю почему там где есть GC нельзя убить укземпляр руками. Но ето уже другая тема в которой я понятия не имею.
ЗЫЫЫ Еще не все сказал
Не нравится почемуто. Надстраивать понимаю, а перестраивать не люблю.
Я имел ввиду что если заказчик хочет одно, а потом у него мысли полезли и ему надо чтото грандиозное что требует такого вот масштабирования - то пускай платит, а фирма будет рефакторить в поте лица.
Ну цитировать без надобности. То был не камень в твой огород, а просто мысля.
Но опять же если роботу отдать и забыть - то почему бы их не использовать.
Профессиональные разработчики имеют обыкновение использовать свой код неоднократно.
Но я бы избавлялся от них не с помощю фабрик. Не нравится мне такой выход. Если я планирую что система будет розвиватся и совсем непонятно как то я бы сделал саму систему сущностю.
Пусть она поддерживает некий интерфейс IRunable и все что в ней должно быть глобальным пускай содержится в етой сущности. Подсистемы етой системы, использующие глобальный ресурс (ну типа синглетоны, статические поля и прочие глобальные переменные) должны хранить ссилку на инстант нашей системы сущности, чтоб получить доступ к общему ресурсу.
Реально глобальной я би сделал только одну самую начальную сущность (к примеру клас со статическим методом, чтото типа public static main), которая будет запускать мою IRunable. Если придется масштабировать или достраивать поверха вверх - просто делаем новий IRunable верхнего уровня, который в себе уже запускает прежние IRunable в сколь-угодном количестве и переделываем наш клас со статической функцией который ету всю кухню запускает.
Конечно предложеную мною сущность системы можно асоциировать с фабрикой - но помоему ето разные вещи. Ето получится не фабрика, а держатель псеглобальных переменных. И не очень напряжет при розроботке первичной системы. Но ето только моя теория. Практически я таког не делал.
Это ты описываешь такую вещь, как "контекст". Собственно, так я и поступил в ситуации описанной в упомянутой статейке. Но это не очень хорошее решение, хранить все в одной большой куче. Плохо по разным причинам. Вообще, с массивными структурами данных трудно управляться. Попробую привести некоторые сложности:
1. Время жизни и актуальность информации.
В идеале надо сразу инициировать весь контекст и единовременно его уничтожать.
Инициировать все сразу может быть неэффективно, а тащить уже полумертвый контекст до конца совсем уж неэффективно.
А если это сделать нельзя? Да в большинстве случаев это сделать сложно.
Получается надо вводить какие-то доп. механизмы, чтоб определять состояние самого контекста.
2. Имея такой единый контекст в системе, может быть довольно сложно выделить и при необходимости вывести из системы конкретную подсистему. Сложно определить взаимосвязи.
3. Большие структуры не наглядны. Они сложны для понимания, а в большой команде или при продолжительной жизни кода, сам черт ногу сломит что в ней надо, а что нет, что к чему относится. А рефакторить такие объемы тяжело. Короче само по себе это противоречит методике "разделяй и влавствуй".
Но в некоторых случаях контекст может быть вполне удовлетворительным решением. Все зависит от ситуации. Серебрянной пули не существует. Однако, я бы предостерег от создания больших структур данных. Структура в идеале должна описываться одним определением, из которого можно однозначно понять её назначение вцелом и назначение её составляющих, например, "координаты точки" - понятно, что отражает структура в целом и каковы её составляющие. "Контекст системы" тоже вроде бы отражает назначение в целом, но вот что именно подразумевается под "контекстом", каковы составляющие этого контекста - это уже головоломка.
ЗЫ. не смотря на то что я сказал "синглетоны не очень хорошо" - проблема не в синглетоне, а в том что мы не можем нормально определится что должно быть глобально а что нет и тыкаем етот паттерн всюду где не надо. Так что я голосую за добро, но теперь буду с етим добром намного осторожнее. :)
Так держать! :)
В идеале в программе должна быть одна единственная глобальная вещь - точка входа. :)
Не нравится почемуто. Надстраивать понимаю, а перестраивать не люблю.
В постоянном надстраивании как раз и кроются проблемы: код запутывается, появляется множество взаимосвязанностей и пр. Поэтому код и архитектуру стоит причесывать. Причем, чем чаще, тем опрятнее она будет.
Я имел ввиду что если заказчик хочет одно, а потом у него мысли полезли и ему надо чтото грандиозное что требует такого вот масштабирования - то пускай платит, а фирма будет рефакторить в поте лица.
Взаимоотношения между заказчиком и исполнителем значительно сложнее, чем "пускай платит, а фирма будет рефакторить". В реальном мире правят заказчики.
В идеале надо сразу инициировать весь контекст и единовременно его уничтожать.
Совсем не обязательно. Я ведь просто предлагаю все глобальные сущности сделать локальными (полями екземпляра) и создать нечто что гарантирует их присутсвие в единичном количестве в пределах етой копии системы. При етом нечто - ето обект а не класс посему его можно создать несколько штук для разных копий системы.
А что глобальные переменные все сразу надо заинициализировать умными вещами ? Вполне достаточно 0, null и создавать по мере необходимости. К примеру Java сама сделает ето для членов класса.
Получается надо вводить какие-то доп. механизмы, чтоб определять состояние самого контекста.
Ето придется делать для всего сложнее "Hello world"
В постоянном надстраивании как раз и кроются проблемы: код запутывается, появляется множество взаимосвязанностей и пр. Поэтому код и архитектуру стоит причесывать. Причем, чем чаще, тем опрятнее она будет.
Взаимоотношения между заказчиком и исполнителем значительно сложнее, чем "пускай платит, а фирма будет рефакторить". В реальном мире правят заказчики.
Всему етому охотно поверю.
А вообще под термином "надстраивание" я имел ввиду не рефакторинг, а возможность использование уже готовой системы А (ту что мы сейчас делаем) как подсистемы чегото большего (надсистемы Б в которой подсистема А может присутствовать в нескольких екземплярах) и чтоб ето все с мимнимумом усилий по стыковке.
По поводу фабрик - возможно для рефакторинга они и будут наилутшим выходом из ситуации (я тут могу только предпологать поскольку рефакторить то и не умею, но учусь :) ), то о чем я говорю скорее применимо для розработки большой еще не совсем понятно какой системы, которая состоит из кучи подсистем. И тут синглетоны действительно неумесны куда ни глянь.
Так держать! :)
Ето стеб ? :)
В идеале в программе должна быть одна единственная глобальная вещь - точка входа. :)
Ну ето стереотип. Для програмы - возможно и так, а для подсистемы можно и точек входа несколько заделать.
В данном случае, я противник тайного голосования.
Объясняйте хоть, на чем основываясь отдаете предпочтение в голосе.
Причем, "зло" - я примерно представляю кто и по каким причинам выбрал.
А вот, "добро" объяснил пока только Rebbit.
[quote=Green;230238]
Получается надо вводить какие-то доп. механизмы, чтоб определять состояние самого контекста.
Ето придется делать для всего сложнее "Hello world"
[/QUOTE]
В том то и дело, что НЕТ.
Нужны данные, - они создаются. Не нужны - их просто нет.
Ето стеб ? :)
Нет, это одобрение, подбадривание...
Ну ето стереотип. Для програмы - возможно и так, а для подсистемы можно и точек входа несколько заделать.
Я не об этом.
А о том, что глобальных вещей, мест где система "прибита гвоздями" должно быть минимум. Система в идеале должна быть инкапсулирована, т.е. связана с внешним миром только входом и выходом, как черный ящик.
Спроси у знатоков функционального программирования. Там вообще нет состояний и система представляет собой именно такой черный ящик.
А множество точек входа - это всего-лишь реализация, концептуально это все та же одна точка входа, а множество - это лишь набор входных параметров.
P.S. Что характерно: в этом опросе зло - безоговорочно, а вот добро - с оговорками.:)
Любое решение должно быть обосновано и, желательно, задокументировано. Код - это, кстати, тоже документ. :)
Ну это так... лирика...
Используя твою метафору с молотком можно задать контекст:
"Молоток при настройке телевизора - это добро или зло?"
Используя твою метафору с молотком можно задать контекст:
"Молоток при настройке телевизора - это добро или зло?"
Ну, опрос же не звучит как "Синглтон при моделировании моделек человечков на 3D Studio Max - добро или зло". Поутрируя можно так же спросить "массив - это добро или зло". Это всего-лишь инструмент.
Ну это так... лирика...[/QUOTE]Ну, я с синглтонами не сталкиваюсь практически, поэтому выдал хоть и своё мнение, но, скажем так, не особо практическое, тогда как критерий истины именно практика. Насколько я понял из обсуждения, синглтон - не зло, но опасная практика. Поэтому проголосовал за добро, ибо опасная практика - не всегда плохая.
Зло в моём понимании - это
define end }
Используя твою метафору с молотком можно задать контекст:
"Молоток при настройке телевизора - это добро или зло?"
В контексте топика синглтон - зло, и опрос, собственно, не нужен, поскольку его использование уже запрещено. :) А вне контекста решения конкретных разработчиков это всего лишь опасная практика.
Зло в моём понимании - это
define end }
Ну в таком случае и про глобальные переменные все же можно сказать, что это не зло, а опасная практика...разве нет?
Для меня, например, критерием злостности в данном случае является глобализация сущностей, что можно сказать и о переменных и синглетонах. Поэтому принципиального различия между ними для меня нет.
А по какому критерию вы относите глобальные переменные ко злу?
Кроме того мой голос я детально прокомментировал с примерами и альтернативой использованию синглетона, о чем и других просил.
К сожалению, не увидел ничего подобного для варианта "добро".
Другими словами, я рассказал, что бывает плохого, если употреблять синглтоны, и как без них обойтись.
Расскажите мне о том, когда без них не обойтись и какие безоговорочные плюсы по сравнению с др. вариантами мы имеем. Не надо мне доказывать, что такие ситуации бывают, просто, покажите конкретные примеры, когда они случаются. Тогда то мы и сможем определиться, в каких случаях этот инструмент стоит применять (и только его) и что случится, если его не применить.
"Это всего-лишь инструмент" - слишком расплывчато, чтоб быть аргументом. Стоп-кран - тоже "всего-лишь инструмент".
Могу согласиться с такой формулировкой: "Это всего-лишь инструмент, которым лучше не пользоваться без КРАЙНЕЙ необходимости", а т.к. настоящие крайности случаются редко (опытный разработчик, просто, не допускает появления крайностей), то лучше вообще не пользоваться.
Думаю это было сделано от лени или поджимающих сроков, либо привлекло то, что из любого места программы можно без особых затруднений получить доступ ко всему и сразу.
По критерию затруднения отладки, каковое проявляется даже в простых приложениях, а если, не дай бог, ещё многопоточность наличествует, то вреда от глобальных переменных становится несравнимо больше пользы.
К сожалению, не увидел ничего подобного для варианта "добро".
Другими словами, я рассказал, что бывает плохого, если употреблять синглтоны, и как без них обойтись.
Расскажите мне о том, когда без них не обойтись и какие безоговорочные плюсы по сравнению с др. вариантами мы имеем. Не надо мне доказывать, что такие ситуации бывают, просто, покажите конкретные примеры, когда они случаются. Тогда то мы и сможем определиться, в каких случаях этот инструмент стоит применять (и только его) и что случится, если его не применить.
"Это всего-лишь инструмент" - слишком расплывчато, чтоб быть аргументом. Стоп-кран - тоже "всего-лишь инструмент".
Могу согласиться с такой формулировкой: "Это всего-лишь инструмент, которым лучше не пользоваться без КРАЙНЕЙ необходимости", а т.к. настоящие крайности случаются редко (опытный разработчик, просто, не допускает появления крайностей), то лучше вообще не пользоваться.
Тогда, как сказал выше Ramon - все паттерны зло. Ведь без любого из них можно спокойно обойтись. Тогда и С++ зло - можно ведь спокойно обойтись и простым С. По-моему не совсем достаточный аргумент, чтобы записать что-нить во зло.
Как насчет добро.. хмм.. по-моему это добро при "защите от дурака". То-есть, если создание двух одинаковых объектов чревато глюками вплоть до крэша - синглтон однозначно становится добром.. Ну например.. если объект работает с каким-либо ресурсом, который невозможно залочить.
Ну как по мне вот тут синглетон вообще ни при чем. Я бы тут точно фабрикой делал. Получаю идентификатор ресурса - отдаю обект для роботы с ним. А синглетон тут не поможет при защите от "дурака". Что мешает обращаться к ресурсу без синглетона-врапера ?
плюсы
...
минусы
1. глобализация сущностей => перекрывает пути к расширению;
2. сложности использования шаблона в динамических библиотеках.
по второму пункту ситуация может возникнуть следующая:
в каждой из нескольких библиотек используется шаблон-синглетон, при подключении их к программе, получим несколько экземпляров, что не отвечает требованиям самого шаблона.
по второму пункту ситуация может возникнуть следующая:
в каждой из нескольких библиотек используется шаблон-синглетон, при подключении их к программе, получим несколько экземпляров, что не отвечает требованиям самого шаблона.
Это что - к программе подключать несколько копий одной и той же библиотеки? Иначе откуда несколько копий одинаковых объектов?
Не, ну если ты будешь использовать ресурсы напрямую, а не через существующие интерфейсы - то у тебя "небольшие" проблемы в проэктировании.
Ты пытаешься сейчас неверно использовать понятие "паттерн".
Паттерн - всего лишь типовое решение, эффективный способ. Ты не можешь решить задачу не используя какой-либо способ. Другое дело, будет ли этот способ типовым и эффективным. Поэтому, скорее всего ты будешь использовать известный паттерн сам того не понимая, что неэффективно, т.к. будешь заново изобретать велосипед.
Тогда и С++ зло - можно ведь спокойно обойтись и простым С. По-моему не совсем достаточный аргумент, чтобы записать что-нить во зло.
Какой аргумент? "Не обойтись"? Так я привел несколько аргументов, это ты прицепился лишь к одному, причем в его полярном варианте. Ещё раз обрати внимание на мой предыдущий пост. Из него можно выделить следущие полярности:
"что бывает плохого" - "безоговорочные плюсы"
"как обойтись" - "когда не обойтись"
Как насчет добро.. хмм.. по-моему это добро при "защите от дурака". То-есть, если создание двух одинаковых объектов чревато глюками вплоть до крэша - синглтон однозначно становится добром.. Ну например.. если объект работает с каким-либо ресурсом, который невозможно залочить.
Уже не раз в этой ветке говорилось, что при этом плюсе он вносит значительный минус - "глобализация" и, как следствие, возможность для других дурацких и "ленивых" ошибок. Приводились другие варианты, не имеющие этих недостатков. Так что данный вариант применения синглетона уже рассмотрен и раскритикован.
Вернемся к нашим баранам(синглтонам) :)
Теперь представим другой вариант. У меня есть фабрика. Причем при инициализации фабрики должен обязательно инициализироваться экземпляр сущности синглтона(что-то вроди статического члена). Тогда создав еще один экземпляр фабрики, я все равно столкнусь с проблемами, если этот "статический" синглтон работает с каким-либо важным незалоченым ресурсом. Тогда получается, что наша фабрика, как сущность, должна быть синглтоном, в классическом понимании этого слова..
Ну, например, множество векторов тоже не знают друг о друге, тем не менее синглетонами их не называют
Вовсе не обязательно
Зачем?
Вместо того чтоб абстрагироваться, лучше определиться с конкретными понятиями и отличительными чертами конкретных паттернов. Ты явно путаешься в этом, что видно из нижеследующего.
Синглтон являет собой некоторую сущность, как и любой другой объект(класс, структура, переменная, неважно). Ты утверждаешь, что фактически нет сущностей, которые существуют в одном экземпляре(так как нам может понадобиться создать две или больше таких сущностей при масштабировании системы), и ты предлагаешь использовать другую сущность(фабрику) для контроля первой сущности, и создавать каждую в своем контексте. То-есть в своей "области видимости" первая сущность останется синглтоном. Грубо говоря у нас появляется n сущностей, каждая из которых не знает про сущевствование остальных. Но, каждая из них остается именно такой(синглтоном).
Следовательно ты не "борешься" с синглтоном, а просто уменьшаешь его область видимости, но сама сущность синглтона так и остается.
Нет, такие сущности не будут синглтонами по определению:
Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Теперь гарантирует не сам объект, а фабрика его породившая.
Сам же объект перестает быть синглтоном.
Вернемся к нашим баранам(синглтонам) :)
Теперь представим другой вариант. У меня есть фабрика. Причем при инициализации фабрики должен обязательно инициализироваться экземпляр сущности синглтона(что-то вроди статического члена).
Почему, "должен обязательно"?
Здесь могут быть совершенно различные механизмы.
Тогда создав еще один экземпляр фабрики, я все равно столкнусь с проблемами, если этот "статический" синглтон работает с каким-либо важным незалоченым ресурсом. Тогда получается, что наша фабрика, как сущность, должна быть синглтоном, в классическом понимании этого слова..
Она может быть синглтоном, а может и не быть. Но дело в другом.
При использовании фабрики за количество (единственность) существования объектов отвечает теперь не сам объект, а именно фабрика.
"Синглтон содержит в себе фабрику единственного экземпляра, а так получается, мы выворачиваем синглтон наизнанку: теперь фабрика содержит экземпляр, а уж единственный он или нет - ей решать."
Если в системе необходимы объекты существующие только в единственном числе, то мы от этого требования никуда не денемся, но при помощи фабрики мы разделяем и смещаем обязанности. При расширении системы значительно проще поменять фабрику, чем сделать синглтон не_синглтоном.
Даже если фабрика - синглтон, то скорее всего при расширении системы понадобиться изменить механизм работы одной фабрики, а не создавать несколько фабрик, т.к. единственная обязанность такой фабрики - создавать контролируемое число других объектов.
{
}
Для нее пусть проектируется класс Солнце, причем для конкретной планеты - есть только одно Солнце
{
}
При создании экземпляра класса планеты - автоматически создается экземпляр Солнца. Поскольку по задумке для планеты существует одно солнце, то логично его сделать Синглтоном(пока не назрела идея расширить мир до двух и больше планет).. При расширении мира - нам удобно сделать фабрику - контролирующую производство наших Синглтонов(солнц), с методом CreateSun, создающим конкретный экземпляр Солнца, для планеты:
{
public:
ID CreateSun(...);
}
Теперь все будет прекрастно работать - для каждой планеты будет свое одно солнце, и фабрика будет контролировать не пытаемся ли мы для какой-то планеты создать еще одно солнце.. Теперь главное - что мешает нам создать две фабрики, и пытаться создать для одной планеты два Солнца - одно в первой, другое во второй фабрике? Думаю, что ничего нам не помешает.. Поэтому - теперь фабрика становится объектом, который идеологически должен быть синглтоном. А кто после этого мешает нам захотеть расширить нашу игровую Вселенную, до некоторого количества миров, в каждом ихз которых будет некоторое количество планет, и мы опять столкнемся с проблемой того, что наша фабрика является синглтоном, так как для каждого мира нам нужно будет использовать отдельную такую фабрику.
Что я хочу этим сказать - что от синглтона невозможно избавиться. Всегда может оказаться, что при расширении системы некоторые объекты - нужно сделать синглтонами, но при последующем расширении, они уже таковыми быть не должны. Поэтому, я например не согласен с высказыванием Green'а, что
Имхо, любой механизм управления объектами программы должен быть синглтоном.
З.Ы. Пример несколько притянут за уши, так как в таком случае можно было сделать экземпляр класса Солнца - переменной класса планеты. Но, мне пока-что некогда думать над более интересным примером.
ЗАЧЕМ ???? :eek: Если у планеты может быть только одно солце (не 0 и не больше) то совсем не обязательно создавать солнце при создании планеты. На мой взгляд ето плохо. В планете нужно сделать поле ссылающееся на ее солнце (ето и так ясно) а для того чтоб не допустить создание планеты без солца нужно передавать солце конструктору планеты и уже в конструкторе проверять чтоб не передали NULL.
Получается, что планета имеет связь типа has с Солнцем...и что получается: значит бомбим планету, а за ней и вся солнечная система гибнет? :)
Логичнее было бы иметь агрегацию планет в солнечной системе.
Можно сделать фабрику солнечных систем, а каждый продукт этой фабрики предоставляет абстрактную фабрику планет. Это дает много возможностей. Например, в зависимости от солнечной системы предоставлять разные фабрики планет. При этом клиент даже не будет подозревать о замене, и весь код по созданию планет останеться неизменным.
Ну а при уничтожении Солнца, логично уничтожить и все вокруг.
{
Singleton::getInstance().callMethod();
}
заменяешь на
{
::createObject().callMethod();
}
но ведь это же те же штаны только впрофиль. Здесь ты даже не пытаешься избавиться от синглтона и утверждаешь, что этого сделать не получается.
Я же предлагаю следущее:
: _object(object)
{}
void Subsystem::func()
{
_object.callMethod();
}
или так
{
::createObject(systemID).callMethod();
}
Я предлагаю не вставлять фабрику на место синглтона, а создать её несколькими уровнями выше. Т.е. объект конструируется не в подсистеме, а передается этой подсистеме уже готовым (см. первый пример кода) или же объект создается с привязкой к подсистеме (см.второй пример кода).
Собственно Rebbit тебе и предложил более аккуратное архитектурное решение, которое соотв. первому варианту кода.
Получается, что планета имеет связь типа has с Солнцем...и что получается: значит бомбим планету, а за ней и вся солнечная система гибнет?
Вовсе нет. Так было бы если б планета содержала в себе объект звезды, а оно содержит только ссылку на звезду. Посему тут связь не "содержит", а "использует" что не перечит реальности, поскольку планета использует звезду ну хотябы чтоб вращаться вокруг нее.
Но введение "солнечной системы" конечно будет необходимо если таких систем будет несколько.
Сори за лирическое отступление.
Все правильно, связь планеты и звезды - "use". Еще добавлю, что для этого примера использование синглетона никаких плюсов не дает. Даже если создать несколько фабрик звездных систем, то ничего страшного не поризойдет, даже наоборот. Сможем одновременно иметь несколько моделей Вселенной :)
з.ы. сказался школьный пробел в астрономии. Имелось ввиду конечно не "солнечная система", а "звездная система". Кстати бывают звездные системы, состоящие из двух и более звезд...:)
Я же предлагаю следущее:
: _object(object)
{}
void Subsystem::func()
{
_object.callMethod();
}
Хмм.. насколько я себе представляю, то в твоем примере object - это твоя фабрика порождающая экземпляры солнца. Насколько я понимаю, именно на нее ты хочешь положить задачу проверки того - кто создает обьект солнца - планета, у которой оно уже есть или новая планета.
Но, в таком случае что мне мешает сделать что-то на подобии:
{
this->func();
Subsystem * temp = new SubSystem();
temp->func();
}
Теперь я могу к одной планете "насильно" привязать второе Солнце...
2 Rebbit
Я не уверен, что передача в конструктор критичных параметров является хорошей идеей. Вот например передам я созданой планете NULL вместо солнца. И что тогда? Использовать прямо в конструкторе сомнительный код вроде:
?? Просто, насколько я себе представляю - передача в конструторе критичных параметров - передает управление объектом самому объекту, а это не есть хорошо.