Wednesday, December 10, 2008

Реализация паттерна "Singleton" в Delphi

Давно интересовала тема реализации шаблона дизайна "Singleton" в Delphi, которая бы мне просто позволила бы мне получить соответствующее поведение путем простого наследования от некоторого базового класса. В результате нескольких различных вариантов реализаций остановился на таком:
type
// Базовый класс для объектов, реализующих паттерн
// "Singleton". Для получения доступа к экземпляру
// необходимо вызвать GetInstance. Если экземпляр
// еще не существует, то он будет создан. Иначе -
// возвращена ссылка на ранее созданный экземпляр.
// Уничтожить экземпляр можно вручную, вызвав Free,
// иначе он будет уничтожен автоматически перед
// завершением приложения
TSingleton = class(TObject)
private
class procedure RegisterInstance(Instance:
TSingletone);
procedure UnRegisterInstance;
class function FindInstance: TSingletone;
protected
// Инициализацию производить только в этом
// конструкторе, а не в GetInstance.
// Не рекомендуется выносить этот конструктор
// из секции protected
constructor Create; virtual;
public
class function NewInstance: TObject; override;
procedure BeforeDestruction; override;
// Точка доступа к экземпляру
constructor GetInstance;
end;
...

implementation

uses Contnrs;

var
SingletonList: TObjectList;

{ TSingleton }

procedure TSingleton.BeforeDestruction;
begin
UnregisterInstance;
inherited BeforeDestruction;
end;

constructor TSingleton.Create;
begin
inherited Create;
end;

class function TSingleton.FindInstance:
TSingletone;
var
i: Integer;
begin
Result := nil;
for i := 0 to SingletonList.Count - 1 do
if SingletonList[i].ClassType = Self
then begin
Result := TSingleton(SingletonList[i]);
Break;
end;
end;

constructor TSingleton.GetInstance;
begin
inherited Create;
end;

class function TSingleton.NewInstance: TObject;
begin
Result := FindInstance;
if Result = nil then begin
Result := inherited NewInstance;
TSingleton(Result).Create;
RegisterInstance(TSingleton(Result));
end;
end;

class procedure TSingleton.RegisterInstance(Instance:
TSingleton);
begin
SingletonList.Add(Instance);
end;

procedure TSingletone.UnRegisterInstance;
begin
SingletonList.Extract(Self);
end;

initialization
SingletonList := TObjectList.Create(True);

finalization
SingletonList.Free;

35 comments:

Anonymous said...
This comment has been removed by a blog administrator.
Petrik Pyatochkin said...

Я вас сильно удивлю, если скажу что Singleton переводится как Одиночка? :) Вашу конструкцию лучше назвать по другому, дабы не вводить в заблуждение неокрепшие умы...

Ins said...

Petrik P'yatochkin, а почему по-Вашему эта конструкция не может быть названа именно Singleton?

airmax2 said...

Согласен с Petrik P'yatochkin
Для начала, вот:
http://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)

P.S. Автор, не мешало бы почистить спам.

Igor Schevchenko said...

Код в Вики (на Delphi), насколько я понимаю, не соответствует утверждению из статьи:

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

Подклассы он порождать не дает, так как явно создает экземпляр класса TSingleton :)

Anonymous said...

Хорошая статья. Действительно было интересно почитать. Не часто такое и встречается та.Наверное стоит подписаться на ваше RSS

Vladix said...

Отличная реализация, браво!

Из того, что я видел - это лучшее решение, которое применимо для повторного использования.

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

Все, что требуется для паттерна Singleton, здесь есть и даже более того:
1) инстанцию класса можно создать только одну;
2) реализация получения инстанции скрывается в одном модуле, т.е. в производных классах не требуется определять дополнительные статические переменные и писать блоки инициализации-финализации
3) код очень хорошо обособлен, им можно пользоваться как черным ящиком.

Посему, если догматическое мышление участников обсуждения не позволяет признать это решение корректным в рамках определения паттерна и помимо всего прочего еще и красивым, то мне их очень жаль

А автору - спасибо!

Ins said...

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

Хотелось бы дополнить, что в некоторых случаях реализовать синглетон можно просто - используя чисто классовые методы (class procedure/function), в этом случае сам класс выступает в качестве единственного и неповторимого экземпляра, а его "единственность" обеспечивается компилятором. То, что классовые методы могут быть виртуальными, делают этот метод достаточно мощным.

Спам вычистил...

Anonymous said...

диета доктора борменталя скачать
диеты скачать


[url=http://dieta.sehost.ru]скачать бесплатную диету
[/url]

Anonymous said...

в тему http://dematom.com/images/2009/08/28/28676-chtoby_plennyh_doprashivati.jpg


_________________
Надо бросить курить, чтобы хвастаться своей силой воли. а

Anonymous said...

Тут кто-нибудь разбирается в радио? Нужен коллега, который рассказал бы вкратце о транзисторе Т2 (не понятно как проверить гв = гв1). Надеюсь, радиолюбители тут “водятся”. Если не по теме совершенно, то извините. Вынужден написать, выхода просто не вижу. ЗЫ: если орфография не правильная то тоже извините, мне 13 лет только. Сайт Ваш правда мало продвинутый и плохопосещаем.Попробуйте оптимизировать его с помощью программного комплекса XRumer 7 Elite (ХРумер 7 Элите) закачать можно тут http://x-rumer.ru/ слышал эффективная программа для раскрутки блог порталов.

Anonymous said...

Интернет магазин ShopForYou.org это оригинальные товары для мужчин и женщин по доступным ценам!
У нас можно встретить большой выбор парфюмерии.

Anonymous said...

Stop hack the program!!!

Anonymous said...

Привет всем, есть вопрос, попался сайт с караоке [url=http://vkone.ru/films/3725-karaoke-4000-pesen-na-blu-rey-22-gb.html]vkone.ru[/url] vkone.ru, не могу разобраться как тут быстро скачать, кто нибудь может пояснить? Заранее спасибо.

Anonymous said...

Ремонтик Под ключ Капитальный жилых помещений в Запорожье http://ukladka-kafelj.ucoz.ua http://vsjstroika.ucoz.ru http://remontkvartiri.at.ua http://vash-remont.ucoz.ua http://ukladkalaminata.at.ua

Anonymous said...

Ремонтик Комплексный Капитальный жилых помещений в Запорожье http://ukladka-kafelj.ucoz.ua http://vsjstroika.ucoz.ru http://remontkvartiri.at.ua http://vash-remont.ucoz.ua http://ukladkalaminata.at.ua

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

Афтар +1

Anonymous said...

ПРОДАМ участок ЧЕЛЯБИНСКАЯ ОБЛАСТЬ МАЛЫЙ КРЕМЕНКУЛЬ, 7СОТОК СОБственость 89080791300 Email: etd09@mail.ru

Anonymous said...

Куплю конденсаторы км-5 H30 (зеленые)
от 1 кг! Предложения на мыло
serg12011974@mail.ru

Anonymous said...

Купил внове встраиваемую мойку Blanco могу говорить полностью доволен приобретением, советую всем поручение делал чрез сайт интернет магазина, обработали быстрее чем я думал, консультанты для сайте вежливые и отзывчивые,нравиться было.)) Вот доказательство для собственноручно сайт,кому надо http://the.dp.ua

Anonymous said...

Купил внове встраиваемую мойку Blanco могу говорить полностью доволен приобретением, советую всем поручение делал чрез сайт интернет магазина, обработали быстрее чем я думал, консультанты для сайте вежливые и отзывчивые,нравиться было.)) Вот доказательство для собственноручно сайт,кому надо http://the.dp.ua

Anonymous said...

Купил внове встраиваемую мойку Blanco могу говорить полностью доволен приобретением, советую всем поручение делал чрез сайт интернет магазина, обработали быстрее чем я думал, консультанты для сайте вежливые и отзывчивые,нравиться было.)) Вот доказательство для собственноручно сайт,кому надо http://the.dp.ua

Anonymous said...

При таком подходе AfterConstruction вызывается дважды.
И вообще, вызывать конструктор дважды - не есть гут - обязательно вылезет в наследниках.
Уберите из "Singleton.GetInstance;" вызов "inherited Create;" и все станет на свои места)) (т.к. он вызывается в NewInstance).

Raziel Sotken said...

Господа, есть тут кто живой?
Собственно: создаю наследника от базового класса TSingleton. Каждый раз при выполнении конструктора Create заново создаются все классы, содержащиеся в этом наследнике. Вставлял проверку - все классы равны nil. Разве смысл одиночки не в том, что экземпляр создается один раз за весь жизненный цикл программы и этим экземпляром можно пользоваться в любой точке приложения? Здесь так не получается, или я чего-то не понимаю?

Raziel Sotken said...

Вопрос снят. Как всегда, виноваты руки и невнимательность. При повторном изучении кода нашел ошибку.

Raziel Sotken said...

Стоп. Рано радоваться) Новая беда: При выходе из приложения сначала выполняется секция finalization, а потом вызывается процедура BeforeDestruction. Получается, что список одиночек у нас уже уничтожен, а мы пытаемся удалить из него объект. Как следствие - трудноуловимый(для меня, по крайней мере) АВ. Не могли бы уважаемые гуру осветить данную проблему и посоветовать решение вопроса? Пока я нашел такое решение: перед обращением к списку делаю проверку:
if Assigned(SingletonList) then
SingletonList.Extract(Self);
Может опять мои кривые грабки где-то напортачили? Подскажите, пожалуйста!

erectile said...

Wow, fantastic blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your website is excellent, let alone the content!

ed pills online said...

Hello! I simply would like to give you a huge thumbs up for your excellent information you've got here on this post. I'll be coming back to your website for more soon.