Создайте статический член, который указывает на текущий класс, ограничьте использование конструкторов для создания класса, сделав их private
#include
using namespace std;
class Singleton {
public:
// С помощью этого клиенты получат доступ к единственному экземпляру
static Singleton* getInstance();
void setValue(int val) {value_ = val;}
int getValue() {return(value_);}
protected:
int value_;
private:
static Singleton* inst_; // Единственный экземпляр
Singleton() : value_(0) {} // частный конструктор
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
// Определяем указатель
static Singleton Singleton* Singleton::inst_ = NULL;
Singleton* Singleton::getInstance() {
if (inst_ == NULL) {
inst_ = new Singleton();
}
return(inst_);
}
int main() {
Singleton* p1 = Singleton::getInstance();
p1->setValue(10);
Singleton* p2 = Singleton::getInstance();
cout << "Value = " << p2->getValue() << '\n';
}
Существует множество ситуаций, когда требуется, чтобы у класса существовал только один экземпляр. Для этой цели служит шаблон Singleton
Когда принимается решение, что требуется только один экземпляр чего-либо, то на ум сразу должно приходить ключевое слово static
static
— это такая, которая может иметь в памяти только один экземпляр. Для отслеживания единственного объекта singleton-класса используйте переменную-член static
, как сделано в примере 8.9.private:
static Singleton* inst_;
Чтобы клиентский код ничего про нее не знал, сделайте ее private
NULL
.Singleton* Singleton::inst_ = NULL;
Чтобы запретить клиентам создавать экземпляры этого класса, сделайте конструкторы private
private:
Singleton() {}
Таким образом, если кто-то попробует создать в куче или стеке новый singleton-класс, то он получит дружественную ошибку компилятора.
Теперь, когда статическая переменная для хранения единственного объекта Singleton
Singleton
ограничено с помощью ограничения конструкторов; все, что осталось сделать, — это предоставить клиентам способ доступа к единственному экземпляру объекта Singleton
. Это делается с помощью статической функции-члена.Singleton* Singleton::getInstance() {
if (inst_ == NULL) {
inst_ = new Singleton();
}
return(inst_);
}
Посмотрите, как это работает. Если указатель static Singleton
NULL
, создается объект. Если он уже был создан, то возвращается его адрес. Клиенты могут получить доступ к экземпляру Singleton
, вызвав его статический метод.Singleton* p1 = Singleton::getInstance();
И если вы не хотите, чтобы клиенты работали с указателями, то можно возвращать ссылку.
Singleton& Singleton::getInstance() {
if (inst_ == NULL) {
inst_ = new Singleton();
}
return(*inst_);
}
Важно здесь то, что в обоих случаях клиентам запрещено создавать экземпляры объекта Singleton
Рецепт 8.3.
8.10. Создание интерфейса с помощью абстрактного базового класса
Требуется определить интерфейс, который будет реализовываться производными классами, но концепция этого интерфейса является абстракцией и не должна наследоваться сама по себе.