Esercizi Singleton Pattern C++
Codegrind Team•Jul 12 2024
Ecco degli esercizi con soluzione per praticare l’utilizzo del Singleton Pattern in C++.
Esercizio 1: Implementazione base del Singleton Pattern
Creare una classe Singleton con un metodo statico per ottenere l'istanza unica.
#include <iostream>
class Singleton {
private:
static Singleton* instance;
Singleton() {}
public:
static Singleton* getInstance() {
if (!instance) {
instance = new Singleton();
}
return instance;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}
Esercizio 2: Singleton con mutex per thread safety
Modificare la classe Singleton per renderla thread-safe usando `std::mutex`.
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
public:
static Singleton* getInstance() {
std::lock_guard<std::mutex> lock(mtx);
if (!instance) {
instance = new Singleton();
}
return instance;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}
Esercizio 3: Singleton con blocco a doppio controllo
Implementare la classe Singleton usando il blocco a doppio controllo per migliorare l'efficienza del thread safety.
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
public:
static Singleton* getInstance() {
if (!instance) {
std::lock_guard<std::mutex> lock(mtx);
if (!instance) {
instance = new Singleton();
}
}
return instance;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}
Esercizio 4: Singleton con distruzione controllata
Implementare la classe Singleton con un distruttore controllato per gestire correttamente la distruzione dell'istanza.
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
~Singleton() {
std::cout << "Distruttore Singleton chiamato" << std::endl;
}
public:
static Singleton* getInstance() {
if (!instance) {
std::lock_guard<std::mutex> lock(mtx);
if (!instance) {
instance = new Singleton();
std::atexit(destroyInstance);
}
}
return instance;
}
static void destroyInstance() {
delete instance;
instance = nullptr;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}
Esercizio 5: Singleton utilizzando std::call_once
Implementare la classe Singleton utilizzando `std::call_once` per garantire l'inizializzazione sicura in ambienti multi-thread.
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::once_flag initFlag;
Singleton() {}
public:
static Singleton* getInstance() {
std::call_once(initFlag, []() {
instance = new Singleton();
});
return instance;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::initFlag;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}
Esercizio 6: Singleton con smart pointer
Implementare la classe Singleton utilizzando `std::shared_ptr` per la gestione automatica della memoria.
#include <iostream>
#include <memory>
#include <mutex>
class Singleton {
private:
static std::shared_ptr<Singleton> instance;
static std::mutex mtx;
Singleton() {}
public:
static std::shared_ptr<Singleton> getInstance() {
std::lock_guard<std::mutex> lock(mtx);
if (!instance) {
instance = std::shared_ptr<Singleton>(new Singleton());
}
return instance;
}
void printMessage() {
std::cout << "Istanza Singleton" << std::endl;
}
};
std::shared_ptr<Singleton> Singleton::instance = nullptr;
std::mutex Singleton::mtx;
int main() {
std::shared_ptr<Singleton> s1 = Singleton::getInstance();
std::shared_ptr<Singleton> s2 = Singleton::getInstance();
s1->printMessage();
std::cout << "s1 e s2 sono uguali: " << (s1 == s2) << std::endl; // Devono essere uguali
return 0;
}