я понимаю, что Singleton — хрестоматийный и, наверное, самый изъезженный и изученный вдоль и поперек шаблон, но помогите мне, начинающему программисту/проектировщику понять зачем же он все-таки нужен, и в какой ситуации мы не можем обойтись глобальной переменной. (в первую очередь речь идет о C++)
...да, да, экземпляр должен быть один — так и не создавать других! Написать один раз в блоке инициализации исходника, реализующего этот класс:
ALaSingleton aLaSingleton();
...по крайней мере, мы сможем быть уверенными, что в конце выполнения для него вызовется деструктор, а с этим дела обстоят не так-то просто в "канонической" реализации Singleton (которая, например, приведена в книге "Банды Четырех").
Нет, я нахожу его весьма удобным во всех случаях кроме того, что я _не могу быть уверенным в том, что все ресурсы, которые взял Singleton_ будут возвращены "на место" при завершении программы (что вызовется какой-нибудь деструктор, другими словами).
Да-да... механизм подсчета ссылок, это, конечно, здорово, но, как мне кажется, он вынуждает контролировать себя еще больше, чем при использовании глобального объекта. Поясняю:
Singleton::Instance()->oper(); // счетчик равен 1
Singleton *s = Singleton::Instance(); //счетчик равен 2 s->FreeInst(); // снова 1
Singleton::Instance()->oper(); // снова 2
и не к чему мне теперь эти FreeInst применять. А если она static,
то я, получается, должен вручную считать сколько раз я обратился
к объекту... весьма стрaнно.
Может. все-таки стоит почитать Александреску? У него неплохо сказано, зачем нужен синглтон. В частности, для того, чтобы контролировать процесс создания/разрушения объектов. И порядок создания/разрушения — это важный момент, особенно, если существуют взаимозависимости между объектами-синглтонами
Хотя в целом, конечно, синглтон — это просто глобальный объект. Но с контролем времени жизни.
SD>Может. все-таки стоит почитать Александреску?
Я непременно его почитаю, просто узнал об этой книге не далее, как вчера, а до этого все мои знания о паттернах базировались на "Гамме".
SD>В частности, для того, чтобы контролировать процесс создания/разрушения объектов.
С контролем над процессом создания — абсолютно согласен, но контроль удаления объекта вызывает сомнения. И, в этом смысле, ни вариант из "Гаммы", ни из статьи Федрова "http://ooad.asf.ru/Patterns/TextFiles/PatternSingleton/list2.asp"
не очень-то устраивает.
Здравствуйте, Hatter, Вы писали:
SD>>Может. все-таки стоит почитать Александреску? H>Я непременно его почитаю, просто узнал об этой книге не далее, как вчера, а до этого все мои знания о паттернах базировались на "Гамме".
SD>>В частности, для того, чтобы контролировать процесс создания/разрушения объектов. H>С контролем над процессом создания — абсолютно согласен, но контроль удаления объекта вызывает сомнения. И, в этом смысле, ни вариант из "Гаммы", ни из статьи Федрова "http://ooad.asf.ru/Patterns/TextFiles/PatternSingleton/list2.asp" H>не очень-то устраивает.
У Александреску проблемы удаления разобраны достаточно подробно, кстати.
Здравствуйте, g_i, Вы писали:
g_i>У Александреску проблемы удаления разобраны достаточно подробно, кстати.
Да-да, есть! Всем большое спасибо! Сегодня скачал Александреску — он ответил на все мои вопросы.
Здравствуйте, Hatter, Вы писали:
H> я понимаю, что Singleton — хрестоматийный и, наверное, самый изъезженный и изученный вдоль и поперек шаблон, но помогите мне, начинающему программисту/проектировщику понять зачем же он все-таки нужен, и в какой ситуации мы не можем обойтись глобальной переменной. (в первую очередь речь идет о C++)
Одно из назначений синглтона — это то, что при обращении к нему, мы можем быть уверены, что объект, которым управляет синглтон уже создан. Глобавльные же переменные такого свойчства не обеспечивают.
Пример:
// Две глобавльные переменные
A a;
B b;
A::A()
{
b.call_some_func();
}
B::B()
{
a.call_another_func();
}
Как можно быть уверенным в том, что на момент вызовов функций классов, объекты a или b уже созданы?
Это решается при помощи синглетонов:
SingletonOfA a;
SingletonOfB a;
A::A()
{
b->call_some_func(); // здесь call_some_func() вызовется точно для уже сконструированного B
}
B::B()
{
a->call_another_func(); // здесь call_another_func() вызовется точно для уже сконструированного A
}
Здравствуйте, Hatter, Вы писали:
g_i>>У Александреску проблемы удаления разобраны достаточно подробно, кстати. H>Да-да, есть! Всем большое спасибо! Сегодня скачал Александреску — он ответил на все мои вопросы.
Ему сказали его почитать, а он его скачал и он ему ответил на все вопросы ... "До чего техника дошла ..." (с). Свободу Александреску!