Два метода реализации режима Singleton в Delphi
Хаози
Аннотация В этой статье описываются две реализации режима Singleton в Delphi и проводится их сравнительный анализ.
Шаблон проектирования ключевых слов, Синглтон
Шаблон Singleton — очень полезный шаблон проектирования. Его цель — просто создать экземпляр класса и предоставить к нему глобальную точку доступа. Глобальные переменные делают объект легко доступным, но не мешают создавать экземпляры нескольких объектов. Целью шаблона Singleton является обеспечение существования только одного экземпляра в течение жизненного цикла программы.
Посмотрите на код ниже:
PROcedure TForm1.Button1Click(Отправитель: TObject);
вар lS1: TSingleton;
S2: ТСинглтон;
начинать
попробуйте lS1 := TSingleton.Create ////Вызов конструктора класса;
lS2 := TSingleton.Create ////Вызов конструктора класса;
//// ...другой код
окончательно
lS1.Free; ////Освободите объект;
lS2.Free; ////Освободите объект;
конец;
конец;
В приведенном выше коде экземпляр класса TSingleton создается при первом вызове функции Create. lS1 указывает на адрес объекта хранения в памяти. Когда функция TSingleton.Create вызывается во второй раз, объект TSingleton создается заново. -экземпляр lS2 указывает на другой адрес выделенной памяти. Шаблон Singleton позволяет самому классу отвечать за сохранение своего единственного экземпляра.
В приведенном выше коде, когда создается ls2, он также указывает на объект, на который указывает ls1 (то есть ему выделяется тот же адрес памяти). Аналогично, мы должны предотвратить освобождение памяти при освобождении ls1, потому что он одиночный. на объект также ссылается ls2. Это гарантирует, что в течение жизненного цикла программы существует только один экземпляр класса.
Пример кода C++ в «Шаблоне проектирования» использует статические переменные-члены C++ для сохранения экземпляров и использует защищенные функции конструктора. Однако, поскольку в Delphi нет статических переменных-членов, метод этого примера одноэлементного режима нельзя использовать как есть. Ниже мы проанализируем несколько способов реализации режима Singleton в DELPHI.
один. Метод, основанный на переопределении двух виртуальных функций Tobject.
функция класса NewInstance: TObject виртуальный;
процедура FreeInstance виртуальная;
Функция NewInstance отвечает за выделение памяти для объекта при создании объекта класса, а FreeInstance наоборот освобождает память.
.
Первый вызывается при создании объекта, а второй — при его уничтожении.
Мы используем две глобальные переменные для хранения одноэлементного объекта и счетчика ссылок на объект.
varInstance: TSingleton = ноль;
RefCount: целое число = 0;
Юниты класса TSingleton:
////---------------------------------------------- -- --------------------------
////
блок uСинглтон;
интерфейс
тип
TSingleton = класс (TObject)
общественный
функция класса NewInstance: TObject; ////Переопределить функцию базового класса;
процедура FreeInstance override; ////Переопределить функцию базового класса;
функция класса RefCount: Integer;////Вернет текущий счетчик ссылок
конец;
//// Объявление глобальных переменных
вар
Экземпляр: TSingleton = ноль;
RefCount: целое число = 0;
выполнение
{ТСинглтон}
процедура TSingleton.FreeInstance;
начинать
Dec( RefCount );////Уменьшаем счетчик ссылок
if (RefCount = 0) then////Это 0, если да, то освободим память
начинать
Экземпляр := ноль;
//// Освободим частные переменные одноэлементного класса
////…
унаследовал FreeInstance;
конец;
конец;
функция класса TSingleton.NewInstance: TObject;
начинать
если (не назначено (экземпляр)), то
начинать
Экземпляр:= TSingleton(унаследованный NewInstance);
////Пример инициализации приватных переменных:
//// Экземпляр.ИмяПеременной := Значение;
конец;
Результат:= Экземпляр;
Inc( RefCount);
конец;
функция класса TSingleton.RefCount: Integer;
начинать
Результат: = RefCount;
конец;
конец.
////---------------------------------------------- -- --------------------------
////
При вызове конструктора TSingleton будет вызвана наша переопределяющая функция NewInstance, а NewInstance выделит память и вернет ее конструктору. Таким образом, с помощью переопределяющей функции NewInstance мы гарантируем, что функция Create может создавать экземпляр только объекта TSingleton. (независимо от того, сколько раз он вызывается) Create возвращает только адрес памяти, выделенный впервые). В то же время переменная RefCount содержит количество ссылок на объект.
Давайте посмотрим на тестовый код
процедура TForm1.Button1Click(Отправитель: TObject);
вар
lS1, lS2: TSingleton;
Ob1, Ob2: Объект;
начинать
lS1 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 1
lS2 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 2
Ob1 := TObject.Create;
Ob2 := Объект.Создать;
если lS1 = lS2, то
ShowMessage('Адреса равны') //// lS1 = lS2
еще
ShowMessage('Адреса не равны');
если Ob1 = Ob2, то
ShowMessage('Адреса равны')
еще
ShowMessage('Адреса не равны'); //// Ob1 <> Ob2
конец;
Когда программа вызывает деструктор (то есть когда вызывается функция FREE), деструктор вызывает функцию FreeInstance, чтобы освободить память, выделенную конструктором. Функция FreeInstance Override гарантирует, что память объекта одноэлементного режима освобождается только тогда, когда счетчик ссылок достигает нуля.
Вот наш тестовый код:
вар
lS1: TSingleton;
lS2: TSingleton;
начинать
пытаться
lS1 := TSingleton.Create ////Вызов конструктора класса;
lS2 := TSingleton.Create ////Вызов конструктора класса;
//// ...другой код
окончательно
lS1.Free; ////Здесь мы сначала вызовем FreeInstance, определенный нашим переопределением,
////Поскольку RefCount равен 1 после уменьшения на 1 в это время, одноэлементный объект не был освобожден.
lS2.Free; ////dec(RefCount)= 0 освобождает одноэлементный объект;
конец;
конец;
Приведенный выше метод реализации шаблона Singleton — хороший способ понять, что класс сам отвечает за сохранение своего собственного уникального экземпляра (путем перехвата запроса на создание нового объекта — см. «Шаблоны проектирования». Особых ограничений на использование он не имеет). класса TSingleton — Программисты могут вызывать функции Create и Free по своему желанию.
Недостатком этого режима является то, что класс TSingleton не может быть унаследован как родительский класс для создания подклассов. Если наследование создает два подкласса, во время создания будет создан только один объект.
процедура TForm1.Button1Click(Отправитель: TObject);
вар
lS1: первая подкатегория;
lS2: вторая подкатегория;
начинать
lS1 := Подкласс 1.Создать;
lS2 := Subclass 2.Create; ////Подкласс 2 не будет создан, lS2 будет указывать на память, на которую указывает lS1,
////То есть lS1 = lS2end;
два. Реализация примера в Delphi из «Шаблоны проектирования».
Примером реализации «Шаблона проектирования» является управление только одним экземпляром объекта с помощью частной функции-конструктора. Однако данная реализация кода C++ не дает информации о том, как высвобождается объект. Функцию Create нельзя приватизировать в Delphi. Мы определяем новую функцию, которая заменяет функцию Create и защищает функцию Create родительского класса. Код выглядит следующим образом
:
////---------------------------------------------- -- --------------------------
////
модуль uSingletonUnit;
интерфейс
использует
Классы, SysUtils;
тип
TCSingleton = class(TComponent) ////Наследуется от класса TcomComponent.
частный
конструктор CreateInstance(AOwner: TComponent); ////Передайте параметр Owner;
//// Таким образом, объект класса TCSingleton будет уничтожен вместе с Владельцем (владелец несет ответственность за уничтожение объекта TCSingleton)
общественный
конструктор Create (AOwner: TComponent override);
Функция класса Экземпляр (AOwner: TComponent): TCSingleton;
конец;
вар
gCSingleton: TCSingleton //// Глобальные переменные;
выполнение
{TCСинглтон}
конструктор TCSingleton.Create(AOwner: TComponent);
начинать
////Защитить функцию Create
поднять Exception.CreateFmt('доступ к классу %s только через экземпляр',
[ИмяКласса]);
конец;
конструктор TCSingleton.CreateInstance(AOwner: TComponent);
начинать
////Вновь определенный конструктор является частным
унаследовано Create(AOwner);
конец;
функция класса TCSingleton.Instance(AOwner: TComponent): TCSingleton;
начинать
если не назначено (gCSingleton), то
gCSingleton: = TCSingleton.CreateInstance(AOwner);
Результат: = gCSingleton;
конец;
конец.
////---------------------------------------------- -- -----------------------------/
/
При использовании вышеуказанного класса реализации программистам не нужно учитывать уничтожение объектов одноэлементного режима. Он просто не может вызвать Create, вы должны вызвать функцию Instance, чтобы получить экземпляр объекта, и передать владельцу синглтона в качестве параметра функции. Этот метод реализации можно унаследовать как базовый класс и использовать в одном элементе шаблона состояния (см. ссылку 4) для достижения полиморфизма во время выполнения.
три. Заключение
Реализацию режима Singleton в Delphi также можно найти в Интернете. Существуют и другие методы реализации. В этой статье описаны два метода.
Самый распространенный и простой. В то же время идеи других методов также очень схожи с двумя вышеперечисленными методами.