Приемы применения статических членов — Singleton



 

Может существовать необходимость в создании специального подвида классов, гарантирующих, что на их основе будет порожден единственный объект. Такая ситуация возникает как при моделировании понятий предметной области (может быть только один центральный банк, одна файловая система, один реестр Windows), так и создании управляющих классов (внутри программы может быть только один экземпляр класса-приложения, один объект доступа к периферийному устройству).

 

Такое ограничение можно выразить в явном виде при помощи статических членов и закрытого конструктора. Класс должен хранить адрес единственного создаваемого объекта, контролировать момент его создания в статическом методе доступа, полностью запрещать конструирование объектов напрямую, а также отвечать за его уничтожение. Классы, обладающие такими свойствами, называют ОДИНОЧКАМИ (Singleton).

 

Ярким примером одиночки может быть класс, реализующий работу с периферийным устройством, например, с принтером. Его реализация может быть очень сложной и зависеть от использования API конкретной операционной системы. Отправка задачи на печать должна скрываться за простым вызовом метода.

 

При этом нельзя допустить, чтобы в программе существовало более одного объекта, управляющего активным принтером. Для экономии вычислительных ресурсов одиночки обычно создаются по первому требованию клиентского кода. Уничтожение откладывают до момента завершения программы. В приведенном ниже примере точкой доступа к принтеру является статический метод GetInstance, который при первом обращении создает объект и запоминает его адрес в статическом поле ms_Instance. Также, применяется статический локальный объект, целью которого является уничтожение объекта-одиночки при выходе из программы - здесь используется свойство языка об обязательном вызове деструктора для объектов в сегменте данных или сегменте стека.

 

printer.hpp

 

#ifndef _PRINTER_HPP_

#define _PRINTER_HPP_

 

/*****************************************************************************/

 

class Printer

{

 

/*-----------------------------------------------------------------*/

 

// Статическая переменная-чден, хранит указатель на созданный объект-одиночку

static Printer * ms_Instance;

 

/*-----------------------------------------------------------------*/

 

// Закрытый конструктор по умолчанию

Printer ();

 

// Закрытый деструктор

~Printer ();

 

/*-----------------------------------------------------------------*/

 

public:

 

// Статический метод доступа к объекту-одиночке

static Printer * GetInstance ();

 

/*-----------------------------------------------------------------*/

 

// Удаленные конструктор копий и оператор присвоения (реализации не будет)

Printer ( const Printer & ) = delete;

Printer& operator = ( const Printer & ) = delete;

 

// Обычный полезный метод

void Print ( const char * _filePath );

};

 

/*****************************************************************************/

 

#endif // _PRINTER_HPP_

 

 

printer.cpp

 

#include "printer.hpp"

 

#include <iostream>

 

/*****************************************************************************/

 

// Определение статической переменной-члена, nullptr по умолчанию

Printer * Printer::ms_Instance;

 

/*****************************************************************************/

 

// Реализация статического метода доступа

Printer * Printer::GetInstance ()

{

// Если это первый вызов, то объекта-одиночки еще не существует,

// и его нужно создать

if ( !ms_Instance )

{

   // Создаем объект-одиночку и запоминаем его адрес

   // в статической переменной-члене

   ms_Instance = new Printer();

 

   // Хитрость: для удаления объекта-одиночки создаем статический локальный

   // объект Destroyer, который уничтожает одиночку в деструкторе.

   // Сам деструктор вызывается после завершения функции main()

   struct Destroyer

   {

       ~ Destroyer () { delete ms_Instance; }

   };

   static Destroyer s_Destroyer;

}

 

// В данной точке объект-одиночка гарантированно существует

return ms_Instance;

}

 

/*****************************************************************************/

 

// Реализация конструктора по умолчанию

Printer::Printer ()

{

// Инициализация...

std::cout << "Printer created..." << std::endl;

}

 

/*****************************************************************************/

 

Printer::~Printer ()

{

// Деинициализация...

std::cout << "Printer destroyed..." << std::endl;

}

 

/*****************************************************************************/

 

void Printer::Print ( const char * _filePath )

{

// Делаем низкоуровневые сложные действия, реализующие печать файла ...

std::cout << "I'm printing..." << std::endl;

}

 

/*****************************************************************************/

 

test.cpp

 

#include “printer.hpp”

 

int main ()

{

// Получаем доступ к объекту-одиночке. Он будет автоматически создан

Printer* printer = Printer::GetInstance();

 

// Печатаем документ

printer->Print( "report.doc" );

}

// После завершения main будет вызван деструктор объекта-одинночки

 

Ниже представлен вывод данной программы:

 

 


Дата добавления: 2021-01-21; просмотров: 51; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!