Примеры использования Паттерн Singleton (Одиночка) | страница 4



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

Листинг 7

>class Singleton {

>protected:

> static Singleton* _self;

> static int _refcount;

> Singleton(){}

virtual ~Singleton() {printf ("~Singleton\n");}

>public:

> static Singleton* Instance();

> void FreeInst();

>};


>class SinglImpl: public Singleton {

>protected:

SinglImpl(){}

>//объявление виртуальным в базовом классе автоматически

> //дает виртуальность в производном.

~SinglImpl() {printf ("~SinglImpl\n");}

>public:

> static Singleton* Instance() {

>  if(!_self) _self = new SinglImpl();

>  _refcount++;

>  return _self;

> }

>};


>void main() {

> Singleton *p = SinglImpl::Instance();

> …

> …

> …

> p->FreeInst();

>}


Результат работы:


~SinglImpl

~Singleton


Иногда может возникнуть ситуация, при которой клиент должен полиморфно работать с объектами, имеющими общий базовый класс, но некоторые из них реализуют паттерн Singleton, а некоторые нет. Проблема возникает в момент освобождения объектов, так как у простых классов нет механизма отслеживания ссылок, а у классов, реализующих Singleton, он есть. При вызове метода FreeInst() через указатель на базовый класс будет вызываться FreeInst() базового класса, не имеющего понятия о подсчете ссылок. Это приведет и к безусловному удалению объектов “Singleton” из памяти. Для предотвращения такого поведения следует объявить виртуальным метод FreeInst() в базовом классе и реализовать специфическое поведение метода для классов Singleton. Реализация FreeInst() в базовом классе предоставляет механизм удаления объектов, не являющихся Singleton’ами.

Листинг 8

>class base {

>protected:

> virtual ~base(){}> //гарантируем удаление только через FreeInst()

>public:

> virtual void Do1()=0;

virtual void FreeInst(){delete this;}

>};


>class Simple: public base {

>protected:

> ~Simple () {printf("Simple::~Simple\n");}

>public:

> void Do1(){printf("Simple::Do1\n");}

>};


>class Singleton: public base {

> static Singleton* _self;

> static int _refcount;

>protected:

> Singleton(){}

> ~Singleton () {printf("Singleton::~Singleton\n");}

>public:

> static Singleton* Instance() {

>  if(!_self) _self = new Singleton ();

>  _refcount++;

>  return _self;

> }

void FreeInst() {_refcount--; if(!_refcount) {delete this; _self=NULL;}}

>void Do1(){printf("Singleton::Do1\n");}

>};


>Singleton* Singleton::_self=NULL;

>int Singleton:: _refcount=0;


>class Client {

> base *objs[2];

> int ind;

>public: