protected:
Application(){}
public:
static Application* Instance();
int loadIniInt(string& section, string& var);
void saveIniInt(string& section, string& var, int val);
void Run();
};
Application* Application::Instance() {
if(!_self) _self = new Application();
return _self;
}
int Application::loadIniInt(string& section, string& var) {
printf('loadIni
');
return 100;
}
void Application::saveIniInt(string& section, string& var, int val) {
printf('saveIni
');
}
void Application::Run() {
wnd=new Window();
//цикл обработки сообщений
delete wnd;
}
Application* Application::_self=NULL;
#include 'app.h'
class Window {
int width;
int height;
public:
Window() {
Application *p=Application::Instance();
p->loadIniInt(string('Window'), string('width'));
p->loadIniInt(string('Window'), string('height'));
}
~Window() {
Application *p=Application::Instance();
p->saveIniInt(string('Window'), string('width'), width);
p->saveIniInt(string('Window'),string('height'), height);
}
};
Этот листинг показывает, как можно организовать каркас оконного приложения, используя паттерн Singleton. Из класса окна требуется доступ к некоторым функциям объекта Application. Поскольку объект приложения существует всегда в одном экземпляре, то он реализует паттерн Singleton, а доступ к объекту приложения из объекта окна осуществляется благодаря методу Instance().
Проблема удаления объекта “Singleton”.
В приведенной выше реализации класса Singleton, есть метод создания объекта, но отсутствует метод его удаления. Это означает, что программист должен помнить в каком месте программы объект удаляется. Другая проблема, связанная с удалением объекта из памяти, возникает при полиморфном использовании объектов класса. Рассмотрим, например, такой код.
class Client {
Singleton * _pS;
public:
SetObject(Singleton *p) {_pS=p;}
~Client(){delete _pS;}
};
void main() {
Client c1,c2;
c1.SetObject(Singleton::Instance());
c2.SetObject(Singleton::Instance());
}
Эта программа будет пытаться удалить дважды один и тот же объект, что приведет к исключительной ситуации в программе. При выходе из контекста функции main, сначала будет вызван деструктор объекта c2, который удалит объект класса Singleton, а затем то же самое попытается сделать и деструктор объекта c1. В связи с этим, хотелось бы иметь механизм, позволяющий автоматически отслеживать ссылки на объект класса Singleton, и автоматически удалять его только тогда, когда на объект нет активных ссылок. Для этого используют специальный метод FreeInst(), удаляющий объект только в случае, если активных ссылок на него нет.
Другая задача, которую надо решить – запрет удаления клиентом объекта Singleton посредством оператора delete. Это решается помещением деструктора в секцию protected.Тем самым, клиенту ничего не остается, как использовать пару Instance()/FreeInst() для управления временем жизни объекта.
class Singleton {
protected:
static Singleton* _self;
static int _refcount;
Singleton(){};
~Singleton(){};
public:
static Singleton* Instance();
void FreeInst() {_refcount--; if(!_refcount) {delete this; _self=NULL;}}
};
В данном примере, в класс Singleton введен счетчик ссылок. Метод FreeInst() вызывает оператор удаления только тогда, когда _refcount равен нулю.