Else
{ // Сигнализируем об ошибке, не создаем объект
assert(!"Invalid student data");
Return nullptr;
}
}
//...
test.cpp
#include “student.hpp”
Int main ()
{
// Создаем студента с корректным баллом через метод-фабрику.
// Ожидаем успех
Student * pStudent = Student::Make("Ivanov", 75);
Assert(pStudent);
Delete pStudent;
// Создаем студента с превышающим допустимый баллом через метод-фабрику.
// Ожидаем неудачу
pStudent = Student::Make(“Petrov”, 101);
assert(! pStudent);
// Создаем студента со слишком маленьким баллом через метод-фабрику.
// Ожидаем неудачу
pStudent = Student::Make(“Sidorov”, 0);
assert(! pStudent);
}
18. Типовое решение Singleton на основе статических членов классов.
Может существовать необходимость в создании специального подвида классов, гарантирующих, что на их основе будет порожден единственный объект. Такая ситуация возникает как при моделировании понятий предметной области (может быть только один центральный банк, одна файловая система, один реестр Windows), так и создании управляющих классов (внутри программы может быть только один экземпляр класса-приложения, один объект доступа к периферийному устройству).
Такое ограничение можно выразить в явном виде при помощи статических членов и закрытого конструктора. Класс должен хранить адрес единственного создаваемого объекта, контролировать момент его создания в статическом методе доступа, полностью запрещать конструирование объектов напрямую, а также отвечать за его уничтожение.
Классы, обладающие такими свойствами, называют ОДИНОЧКАМИ (Singleton).
Ярким примером одиночки может быть класс, реализующий работу с принтером.
При этом нельзя допустить, чтобы в программе существовало более одного объекта, управляющего активным принтером. В приведенном ниже примере точкой доступа к принтеру является статический метод GetInstance, который при первом обращении создает объект и запоминает его адрес в статическом поле ms_Instance. Также происходит подписка на автоматическое удаление объекта-одиночки, используя механизм atexit.
printer.hpp
#ifndef _PRINTER_HPP_
#define _PRINTER_HPP_
Class Printer
{ // Статическая переменная-чден, хранит указатель на созданный объект-одиночку
static Printer * ms_Instance;
// Закрытый конструктор по умолчанию
Printer ();
// Закрытый деструктор
~Printer ();
// Закрытый конструктор копий и оператор присвоения (реализации не будет)
Printer (const Printer &);
Printer& operator = (const Printer &);
// Статический метод уничтожения объекта-одиночки
Static void DestroyInstance ();
public:
// Статический метод доступа к объекту-одиночке
static Printer * GetInstance ();
// Обычный полезный метод
void Print (const char * _filePath);
};
#endif // _PRINTER_HPP_
printer.cpp
#include “printer.hpp”
// Определение статической переменной-члена, nullptr по умолчанию
Printer * Printer::ms_Instance;
// Реализация статического метода доступа
Printer * Printer::GetInstance ()
{ // Если это первый вызов, то объекта-одиночки еще не существует,
// и его нужно создать
if (! ms_Instance)
{ // Создаем объект-одиночку и запоминаем его адрес
// в статической переменной-члене
ms_Instance = new Printer();
// Подписываемся на вызов функции уничтожения после выхода из main
atexit(& Printer::DestroyInstance);
}
// В данной точке объект-одиночка гарантированно существует
Return ms_Instance;
}
// Реализация статического метода уничтожения одиночки
void Printer::DestroyInstance ()
{ delete ms_Instance;
ms_Instance = nullptr;
}
// Реализация конструктора по умолчанию
Printer::Printer ()
{ // Выполняем захват необходимых ресурсов операционной системы
//...
}
Printer::~Printer ()
{ // Выполняем освобождение захваченных ресурсов операционной системы
//...
}
void Printer::Print (const char * _filePath)
{ // Делаем низкоуровневые сложные действия, реализующие печать файла
//...
}
test.cpp
#include “printer.hpp”
Int main ()
{ // Получаем доступ к объекту-одиночке. Он будет автоматически создан
Printer* printer = Printer::GetInstance();
// Печатаем документ
printer->Print("report.doc");
}
// После завершения main будет вызвана функция Printer::DestroyInstance,
// которая уничтожит объект-одиночку