控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)
实现代码:
#include <sstream>
#include <string>
#include <unordered_map>
#include <memory>
#include <functional>
#include "anyval.h"
#include "noncopyable.h"
#include "singleton.h"
class IocContainer : public noncopyable
{
public:
IocContainer() {}
~IocContainer() {}
template<class T, typename Depend, typename... Args>
typename std::enable_if<!std::is_base_of<T, Depend>::value>::type RegisterType(const std::string& strKey)
{
std::function<T* (Args...)> function = [](Args... args) {
return new Depend(args...);
};
RegisterType(strKey, function);
}
template<class T, typename Depend, typename... Args>
typename std::enable_if<std::is_base_of<T, Depend>::value>::type RegisterType(const std::string& strKey)
{
std::function<T* (Args...)> function = [](Args... args) {
return new Depend(args...);
};
RegisterType(strKey, function);
}
template<class T, typename... Args>
T* Resolve(const std::string& strKey, Args... args)
{
auto iter = m_creatorMap.find(strKey);
if (m_creatorMap.end() == iter)
{
return NULL;
}
AnyVar resolver = iter->second;
std::function<T* (Args...)> function = any_cast<std::function<T* (Args...)>>(resolver);
return function(args...);
}
template<class T, typename... Args>
std::shared_ptr<T> ResolveShared(const std::string& strKey, Args... args)
{
T* tmp = Resolve<T, Args...>(strKey, args...);
return std::shared_ptr<T>(tmp);
}
private:
void RegisterType(const std::string& strKey, AnyVar constructor)
{
if (m_creatorMap.end() != m_creatorMap.find(strKey))
{
throw std::invalid_argument(strKey + " : this key has already exist!");
}
else
{
m_creatorMap.emplace(strKey, constructor);
}
}
private:
std::unordered_map<std::string, AnyVar> m_creatorMap;
};
typedef Singleton<IocContainer> IocContainerAgent;
测试代码:
class TestBase
{
public:
virtual void show() = 0;
};
class TestIoc : public TestBase
{
public:
TestIoc(int a, const std::string& msg)
{
}
void show()
{
std::cout << "this is TestIoc" << std::endl;
}
};
int main()
{
IocContainerAgent::get_instance().RegisterType<TestBase, TestIoc, int, std::string>("testIoc");
TestBase* pTest = IocContainerAgent::get_instance().Resolve<TestBase>("testIoc", 10, std::string("msg"));
pTest->show();
return 1;
}