Читать «Примеры использования Паттерн Singleton (Одиночка)» онлайн - страница 2
Дмитрий Федоров
ПРИМЕЧАНИЕ Конструктор класса объявлен в защищенной секции. Благодаря этому отсутствует возможность создавать объекты класса по оператору new или статически. Вместо этого для конструирования объекта служит метод Instance(), который гарантирует, что в программе будет существовать только один экземпляр данного класса.
Таким образом, класс Singleton инкапсулирует в себе методы и свойства данной сущности, может быть доступен из любого места программы благодаря методу Instance(), а, кроме того, теперь мы можем управлять временем жизни этого объекта. Вот пример использования класса Singleton:
#include "app.h"
void main() {
Application* application = Application::Instance();
application->Run();
delete application;
}
#include <string>
using std::string;
class Window;
class Application {
static Application* _self;
Window *wnd;
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\n");
return 100;
}
void Application::saveIniInt(string& section, string& var, int val) {
printf("saveIni\n");
}
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(), удаляющий объект только в случае, если активных ссылок на него нет.