|
1 | 1 | // cppcheck-suppress-file [functionStatic] |
2 | 2 |
|
3 | | -// Singleton is a creational design pattern that lets you ensure that a class |
4 | | -// has only one instance, while providing a global access point to this |
5 | | -// instance. Appicability: |
6 | | -// (*) when a class in your program should have just a single instance |
7 | | -// available to all clients; for example, a single database object shared by |
8 | | -// different parts of the program. |
9 | | -// (**) when you need stricter control over global variables. |
10 | | - |
11 | | -// UML: docs/uml/patterns_creational_singleton.drawio.svg |
12 | | - |
13 | 3 | #include <string> |
| 4 | +#include "ExampleRegistry.h" |
14 | 5 | #include "Logger.h" |
15 | 6 |
|
16 | 7 | namespace { |
17 | 8 | namespace singleton_pattern { |
18 | 9 |
|
19 | | -/** |
20 | | - * The Singleton class defines the `GetInstance` method that serves as an |
21 | | - * alternative to constructor and lets clients access the same instance of this |
22 | | - * class over and over. |
23 | | - */ |
24 | | -class Singleton { |
25 | | - private: |
26 | | - static inline Singleton* instance_ = nullptr; |
27 | | - static inline int id_ = 0; |
28 | | - int dummy_{}; |
29 | | - /** |
30 | | - * The Singleton's constructor should always be private to prevent direct |
31 | | - * construction calls with the `new` operator. |
32 | | - */ |
33 | | - Singleton() = default; |
| 10 | +/// @class Singleton class |
| 11 | +/// @brief defines the `GetInstance` method that serves as an alternative to constructor |
| 12 | +class SingletonConfig { |
34 | 13 |
|
35 | 14 | public: |
36 | 15 | // 1. Should not be cloneable. |
37 | | - Singleton(const Singleton& other) = delete; |
| 16 | + SingletonConfig(const SingletonConfig& other) = delete; |
38 | 17 |
|
39 | 18 | // 2. Should not be assignable |
40 | | - Singleton& operator=(const Singleton& other) = delete; |
| 19 | + SingletonConfig& operator=(const SingletonConfig& other) = delete; |
41 | 20 |
|
42 | | - static Singleton* get_instance() { |
43 | | - if (instance_ == nullptr) { |
44 | | - instance_ = new Singleton(); |
45 | | - id_++; |
46 | | - } |
47 | | - LOG("id: " + std::to_string(id_)); |
48 | | - return instance_; |
| 21 | + static SingletonConfig& get_instance() { |
| 22 | + static SingletonConfig instance; |
| 23 | + return instance; |
49 | 24 | } |
50 | 25 |
|
51 | | - void operation() { |
52 | | - LOG("id: " + std::to_string(id_)); |
53 | | - dummy_++; |
| 26 | + void init(const std::string& input) { |
| 27 | + LOG(input); |
| 28 | + value_ = input; |
54 | 29 | } |
| 30 | + |
| 31 | + const std::string& get_value() const { |
| 32 | + LOG(""); |
| 33 | + return value_; |
| 34 | + }; |
| 35 | + |
| 36 | + private: |
| 37 | + /// @brief Default constructor should always be private |
| 38 | + SingletonConfig() = default; |
| 39 | + std::string value_; |
55 | 40 | }; |
56 | 41 |
|
57 | 42 | void run() { |
58 | | - auto client_code = [](Singleton* s) { |
59 | | - s->operation(); |
| 43 | + auto client_code = []() { |
| 44 | + LOG(SingletonConfig::get_instance().get_value()); |
60 | 45 | }; |
61 | 46 |
|
62 | | - Singleton* s1 = Singleton::get_instance(); |
63 | | - client_code(s1); |
64 | | - |
65 | | - Singleton* s2 = Singleton::get_instance(); |
66 | | - client_code(s2); |
| 47 | + SingletonConfig& s1 = SingletonConfig::get_instance(); |
| 48 | + s1.init("0x001"); |
| 49 | + client_code(); |
67 | 50 |
|
68 | 51 | // Singleton* s3 = new Singleton(); // ERROR |
69 | 52 | } |
70 | 53 |
|
71 | 54 | } // namespace singleton_pattern |
72 | 55 | } // namespace |
73 | 56 |
|
74 | | -#include "ExampleRegistry.h" |
75 | | - |
76 | 57 | class SingletonExample : public IExample { |
77 | 58 | public: |
78 | 59 | std::string group() const override { return "dp/creational"; } |
|
0 commit comments