ServiceProvider: Better naming of methods
This commit renames methods of ServiceProvider to be easier to understand. It also replaces the misleading singleton with more correct here global instance of class.
This commit is contained in:
@@ -26,8 +26,7 @@
|
||||
|
||||
#include "ServiceProvider.h"
|
||||
|
||||
Base::ServiceProvider& Base::ServiceProvider::get()
|
||||
namespace Base
|
||||
{
|
||||
static Base::ServiceProvider instance;
|
||||
return instance;
|
||||
Base::ServiceProvider globalServiceProvider;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,49 @@
|
||||
namespace Base
|
||||
{
|
||||
|
||||
/**
|
||||
* Class that implements basic service container that can be used to obtain different implementation
|
||||
* of various services.
|
||||
*
|
||||
* Primary use of such container is to provide ability to define global services that can be
|
||||
* implemented within non-core modules. This for example allows to use code that is available only
|
||||
* in Part module from Base with the only requirement being that Part implements specific interface
|
||||
* and registers the service within service provider.
|
||||
*
|
||||
* For ease of use global service provider instance is provided with convenience functions:
|
||||
* - Base::provideService
|
||||
* - Base::provideServiceImplementations
|
||||
* - Base::registerServiceImplementation
|
||||
*
|
||||
* As the example, we can define service that provides placement of sub objects in App:
|
||||
* @code
|
||||
* class SubObjectPlacementProvider
|
||||
* {
|
||||
* public:
|
||||
* virtual Base::Placement calculate(SubObjectT object, Base::Placement basePlacement) const =
|
||||
* 0;
|
||||
* };
|
||||
* @endcode
|
||||
*
|
||||
* App does not know how to implement this service, but it can be implemented within Part module:
|
||||
* @code
|
||||
* class AttacherSubObjectPlacement final: public App::SubObjectPlacementProvider { ... }
|
||||
*
|
||||
* // later in module initialization method
|
||||
*
|
||||
* Base::registerServiceImplementation<App::SubObjectPlacementProvider>(new
|
||||
* AttacherSubObjectPlacement);
|
||||
* @endcode
|
||||
*
|
||||
* This service can then be obtained inside other modules, without them being aware of the
|
||||
* implementation - only the interface:
|
||||
*
|
||||
* @code
|
||||
* auto subObjectPlacementProvider = Base::provideService<App::SubObjectPlacementProvider>();
|
||||
* @endcode
|
||||
*
|
||||
* This function can (and should) be used as default for constructor injection of services.
|
||||
*/
|
||||
class BaseExport ServiceProvider
|
||||
{
|
||||
struct ServiceDescriptor
|
||||
@@ -106,35 +149,53 @@ public:
|
||||
* @tparam T Service interface
|
||||
*/
|
||||
template<typename T>
|
||||
void implement(T* contract)
|
||||
void registerImplementation(T* contract)
|
||||
{
|
||||
ServiceDescriptor descriptor {typeid(T).name(), contract};
|
||||
|
||||
_implementations[typeid(T).name()].push_front(descriptor);
|
||||
}
|
||||
|
||||
static ServiceProvider& get();
|
||||
|
||||
private:
|
||||
std::map<const char*, std::deque<ServiceDescriptor>> _implementations;
|
||||
};
|
||||
|
||||
BaseExport extern ServiceProvider globalServiceProvider;
|
||||
|
||||
/**
|
||||
* Obtains primary implementation of requested service from the global service provider.
|
||||
*
|
||||
* @tparam T Service kind to obtain.
|
||||
* @return Primary implementation of the service or nullptr if there is no implementation available.
|
||||
*/
|
||||
template<typename T>
|
||||
T* provideImplementation()
|
||||
T* provideService()
|
||||
{
|
||||
return ServiceProvider::get().provide<T>();
|
||||
return globalServiceProvider.provide<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains all available implementations of requested service in the global service provider.
|
||||
*
|
||||
* @tparam T Service kind to obtain.
|
||||
* @return List of available service implementation.
|
||||
*/
|
||||
template<typename T>
|
||||
std::list<T*> provideAllImplementations()
|
||||
std::list<T*> provideServiceImplementations()
|
||||
{
|
||||
return ServiceProvider::get().all<T>();
|
||||
return globalServiceProvider.all<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers implementation of service in the global service provider.
|
||||
*
|
||||
* @tparam T Service kind to obtain.
|
||||
* @return List of available service implementation.
|
||||
*/
|
||||
template<typename T>
|
||||
void implementContract(T* implementation)
|
||||
void registerServiceImplementation(T* implementation)
|
||||
{
|
||||
ServiceProvider::get().implement<T>(implementation);
|
||||
globalServiceProvider.registerImplementation<T>(implementation);
|
||||
}
|
||||
|
||||
} // namespace Base
|
||||
|
||||
@@ -62,7 +62,7 @@ TEST(ServiceProvider, provideImplementation)
|
||||
// Arrange
|
||||
Base::ServiceProvider serviceProvider;
|
||||
|
||||
serviceProvider.implement<SimpleService>(new FirstServiceImplementation);
|
||||
serviceProvider.registerImplementation<SimpleService>(new FirstServiceImplementation);
|
||||
|
||||
// Act
|
||||
auto implementation = serviceProvider.provide<SimpleService>();
|
||||
@@ -77,8 +77,8 @@ TEST(ServiceProvider, provideLatestImplementation)
|
||||
// Arrange
|
||||
Base::ServiceProvider serviceProvider;
|
||||
|
||||
serviceProvider.implement<SimpleService>(new FirstServiceImplementation);
|
||||
serviceProvider.implement<SimpleService>(new SecondServiceImplementation);
|
||||
serviceProvider.registerImplementation<SimpleService>(new FirstServiceImplementation);
|
||||
serviceProvider.registerImplementation<SimpleService>(new SecondServiceImplementation);
|
||||
|
||||
// Act
|
||||
auto implementation = serviceProvider.provide<SimpleService>();
|
||||
@@ -93,8 +93,8 @@ TEST(ServiceProvider, provideAllImplementations)
|
||||
// Arrange
|
||||
Base::ServiceProvider serviceProvider;
|
||||
|
||||
serviceProvider.implement<SimpleService>(new FirstServiceImplementation);
|
||||
serviceProvider.implement<SimpleService>(new SecondServiceImplementation);
|
||||
serviceProvider.registerImplementation<SimpleService>(new FirstServiceImplementation);
|
||||
serviceProvider.registerImplementation<SimpleService>(new SecondServiceImplementation);
|
||||
|
||||
// Act
|
||||
auto implementations = serviceProvider.all<SimpleService>();
|
||||
|
||||
Reference in New Issue
Block a user