控制反轉(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;
}