Definition
The singleton pattern ensures a class has only one instance and provides global access.
Scenario
We want to have a globally accessible place to hold stuff.
Many people argue that we shouldn’t use singleton pattern, and we only use it when we are 100% sure that we only need a single instance. This is because when something is globally accessible, that thing might change without you knowing it, and it will be hard to do unit test.
Class Diagram
We only initialize one instance by making the instance a static variable instance_
and making the constructor private. When getting the instance (GetInstance
) for the first time, since it is also the class’s member, it can call the private constructor to initialize the instance. We cannot initialize the instance from outside. After initialization, it will simply return the initialized instance. Copy constructor and assign operation (=
) are deleted, so we cannot create a second instance by copying or reassigning by =
.
Used Cases
- Indicating what the current state a machine is in right now.
Implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// singleton.h
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
#include <memory>
class Singleton {
private:
static Singleton* instance_;
Singleton();
public:
static Singleton& GetInstance();
int global_val;
Singleton(const Singleton& other) = delete;
Singleton& operator=(const Singleton& other) = delete;
~Singleton();
};
#endif //__SINGLETON_H__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "singleton.h"
Singleton* Singleton::instance_ = nullptr;
Singleton& Singleton::GetInstance() {
if (instance_ == nullptr) {
instance_ = new Singleton();
}
return *instance_;
}
Singleton::Singleton() : global_val(1) {}
Singleton::~Singleton() { delete instance_; }
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include "singleton.h"
int main () {
std::cout << "global_val = " << Singleton::GetInstance().global_val << std::endl;
Singleton::GetInstance().global_val = 100;
std::cout << "global_val = " << Singleton::GetInstance().global_val << std::endl;
return 0;
}