Singleton* Singleton::_self=NULL;

int Singleton:: _refcount=0;

class Client {

 base *objs[2];

 int ind;

public:

 Client(){  objs[0]=NULL;objs[1]=NULL;ind=0; }

 ~Client() {

  for(int i=0;i<ind;i++) objs[i]->FreeInst();

 }

 void Add(base *p){if(ind<2) objs[ind++]=p;}

 void Do() {

  for(int i=0;i<ind;i++) objs[i]->Do1();

 }

};

void main() {

 Client cl;

 cl.Add(Singleton::Instance());

 cl.Add(new Simple());

cl.Do();

}

результат работы программы:

Singleton::Do1 Simple::Do1 Singleton::~Singleton Simple::~Simple

В данном примере при разрушении объект класса Client автоматически вызываются методы FreeInst() для каждого из хранимых указателей. Благодаря тому, что этот метод объявлен виртуальным, а в классах реализующих паттерн Singleton этот метод переопределен с учетом подсчета ссылок, то программа работает именно так как ожидается.

Применение шаблонов языка C++.

Альтернативой приведенной выше реализации может служить реализация класса Singleton при помощи шаблонов языка С++. Преимущество такого подхода заключается в автоматической параметризации метода Instance(), что приводит к отсутствию необходимости переопределять его в классах потомках. По изложенным ранее причинам конструктор класса-потомка также должен быть объявлен защищенным, а деструктор виртуальным. Кроме того, базовый класс Singleton должен быть объявлен другом класса наследника, поскольку метод Instance() базового класса в этой модели создает объект производного класса.

листинг 9

template <class T>

class Singleton {

 static T* _self;

 static int _refcount;

protected:

 Singleton(){}

 virtual ~Singleton(){_self=NULL;}

public:

 static T* Instance();

 void FreeInst();

};

template <class T>

T* Singleton<T>::_self = NULL;

template <class T>

int Singleton<T>::_refcount=0;

template <class T>

T* Singleton<T>::Instance() {

 if(!_self) _self=new T;

 _refcount++;

 return _self;

}

template <class T>

void Singleton<T>::FreeInst() {

 if(--_refcount==0) delete this;

}

class Derived: public Singleton<Derived> {

protected:

 Derived(){}

 friend class Singleton<Derived>;

};

int main(int argc, char* argv[]) {

 Derived *p = Derived::Instance();

 …

 …

 …

 p->FreeInst();

 return 0;

}

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату