Service Container Implementation
This article demonstrates the implementation of a singleton service management system using C++.
Service Container Class Features:
- Register singleton types (default constructor)
- Register singleton types (interface and implementation with default constructor)
- Register singleton types (with custom factory function)
- Retireve singleton instances
These methods utilize std::mutex for thread safety.
Service Manager Class Features:
- Private methods: register singleton types, initialize services, deinitialize services
- Public method: get service container object pointer
- Service Container Class (ServiceContainer.h) ===============================================
#ifndef SERVICECONTAINER_H
#define SERVICECONTAINER_H
#include <unordered_map>
#include <typeindex>
#include <memory>
#include <functional>
#include <mutex>
class ServiceContainer
{
public:
explicit ServiceContainer() {}
// Register singleton type (default constructor)
template<typename t="">
void registerSingleton()
{
std::lock_guard<:mutex> lock(m_mutex);
// Store default constructor for the type
m_factoryMap[std::type_index(typeid(T))] = []() { return std::make_shared<t>(); };
}
// Register singleton type (interface and implementation, default constructor)
template<typename implementationtype="" interfacetype="" typename="">
void registerSingleton()
{
std::lock_guard<:mutex> lock(m_mutex);
static_assert(std::is_base_of<interfacetype implementationtype="">::value, "ImplementationType must inherit from InterfaceType");
// Store default constructor for the interface type
m_factoryMap[std::type_index(typeid(InterfaceType))] = []() { return std::make_shared<implementationtype>(); };
}
// Register singleton type (with custom factory function)
template<typename t="">
void registerSingleton(std::function<:shared_ptr>()> factory)
{
std::lock_guard<:mutex> lock(m_mutex);
m_factoryMap[std::type_index(typeid(T))] = [factory]()
{
return std::static_pointer_cast<void>(factory());
};
}
// Get singleton instance (lazy initialization)
template<typename t="">
std::shared_ptr<t> resolve()
{
// Check if type is registered
auto typeIndex = std::type_index(typeid(T));
auto factoryIt = m_factoryMap.find(typeIndex);
if (factoryIt == m_factoryMap.end())
{
throw std::runtime_error("Type not registered: " + std::string(typeid(T).name()));
}
// Check if instance already created
auto instanceIt = m_instanceMap.find(typeIndex);
if (instanceIt == m_instanceMap.end())
{
// Lock for instance creation
std::lock_guard<:mutex> lock(m_mutex);
// Create and store instance
auto instance = factoryIt->second();
m_instanceMap[typeIndex] = instance;
return std::static_pointer_cast<t>(instance);
}
// Return existing instance
return std::static_pointer_cast<t>(instanceIt->second);
}
private:
// Dictionary storing type constructors
std::unordered_map<:type_index std::function="">()>> m_factoryMap;
// Dictionary storing singleton instances
std::unordered_map<:type_index std::shared_ptr="">> m_instanceMap;
// Thread safety mutex
std::mutex m_mutex;
};
#endif // SERVICECONTAINER_H
</:type_index></:type_index></t></t></:mutex></t></typename></void></:mutex></:shared_ptr></typename></implementationtype></interfacetype></:mutex></typename></t></:mutex></typename></mutex></functional></memory></typeindex></unordered_map>
- Service Manager Class ========================
2.1 Service Manager Header File (ServiceManager.h)
#ifndef SERVICEMANAGER_H
#define SERVICEMANAGER_H
#include "ServiceContainer.h"
class ServiceManager
{
public:
~ServiceManager();
static ServiceManager& getInstance();
void initialize();
void shutdown();
std::shared_ptr<servicecontainer> getContainer() const { return m_container; }
private:
ServiceManager();
void registerServices();
void initializeServices();
void deinitializeServices();
private:
std::shared_ptr<servicecontainer> m_container;
};
#endif // SERVICEMANAGER_H
</servicecontainer></servicecontainer>
2.2 Service Manager Implementation (ServiceManager.cpp)
#include "ServiceManager.h"
#include "LoggingService.h"
#include "ConfigurationService.h"
ServiceManager::ServiceManager()
: m_container(std::make_shared<servicecontainer>())
{
registerServices();
}
ServiceManager::~ServiceManager()
{
}
ServiceManager& ServiceManager::getInstance()
{
static ServiceManager instance;
return instance;
}
void ServiceManager::initialize()
{
initializeServices();
}
void ServiceManager::shutdown()
{
deinitializeServices();
}
/// <summary>
/// Register services
/// </summary>
void ServiceManager::registerServices()
{
// Register singleton services
m_container->registerSingleton<loggingservice>();
m_container->registerSingleton<configurationservice>();
}
void ServiceManager::initializeServices()
{
auto loggingService = m_container->resolve<loggingservice>();
loggingService->initialize();
auto configService = m_container->resolve<configurationservice>();
configService->loadConfiguration();
}
void ServiceManager::deinitializeServices()
{
auto loggingService = m_container->resolve<loggingservice>();
loggingService->shutdown();
}
</loggingservice></configurationservice></loggingservice></configurationservice></loggingservice></servicecontainer>
- Service Manager Application ==============================
3.1 Main Window Header (MainWindow.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <qmainwindow>
#include "LoggingService.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
LoggingService *m_loggingService;
};
#endif // MAINWINDOW_H
</qmainwindow>
3.2 Main Window Implementation (MainWindow.cpp)
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_loggingService = new LoggingService();
m_loggingService->initialize();
}
MainWindow::~MainWindow()
{
m_loggingService->shutdown();
delete m_loggingService;
}