-
Notifications
You must be signed in to change notification settings - Fork 0
Home
jijinlong edited this page Nov 14, 2016
·
15 revisions
##C++依赖注入实现 我们的目标就是 能够影藏具体的实现,并且可以抽选相关的实现,使用时只约定接口即可。
// 定义的接口
IAction action;
// 选择相关的实现,在配置文件中通过ActionImp 抽选相关的实现为action赋值
action.imp("ActionImp");
//注意这里的-> 他是会调用的具体实现的方法
action->doSometing(); 怎么能做到这点呢?我们一步步来,先实现基础的Interface类
template<typename T>
class Interface {
public:
// 重载-> 调用子类相关函数
T * operator->()
{
if (_buffer == 0) return 0;
return static_cast<T*>((void*)_buffer);
}
Interface()
{
_buffer = 0;
}
virtual ~Interface()
{
// 注意并不是直接delete _buffer ,若是将无法调用实现的析构
if (_buffer) delete static_cast<T*>((void*)_buffer); _buffer = 0;
}
protected:
void* _buffer; // 具体实现类 所使用 的空间
};为什么不用 纯虚函数呢? 对象在使用时必须有实现,不然C++无法分配内存,所有必须是个包含空实现的虚函数来做,我们是需要在运行期指定实现的。我们定义IAction 来继承Interface 类,Interface类帮我们实现了->重载 可以让C++为我们自动调用实现类的方法。
class IAction:public Interface<IAction> {
public:
virtual void doSometing(){}; // 空实现 必须是虚函数
virtual ~IAction(){}; // 务必加上
void imp(const char *name); // 指定使用实现的类
};我们来定义一个实现
class ActionImp:public IAction {
public:
void doSometing(){
printf("dosometing"); // 就输出字符串
}
};我们怎么将 IAction 与 ActionImp 对应呢?简单的方式,为IAction 提供一个方法,在这个方法里 指定具体的实现
void IAction::imp(const char *name)
{
if (name == "ActionImp")
{
_buffer = new ActionImp(); // 根据字符串来产生不同的实现
}
}这也是一种方法,很LOW,如果你觉得够用就这样用,但是我们希望代码少做这些 If Else 写一个基础的工厂来生产这些对象
void IAction::imp(const char *name)
{
_buffer = ObjectFactory::instance()->create(name); // 这样是不是更好?
}如何实现这样的ObjectFactory 呢?
最简单的办法 就是 ObjectFactory 根据名字分发生产对象,就是if else 的方式,我们这里通过hashmap 存放相关实现,通过名字抽选出具体的产出类,然后clone 生成当前对象
class Implement{
public:
// 容器中存放相关不同实现的对象
virtual void *clone(){return 0;};
}
template<typename T>
class Implement : public Implement{
public:
T *clone()
{
return new T();
}
};
// ActionImp 需要 继承ImplementCreator
// 其实就是为了你少写个 clone() 函数 你 继承Implement 实现 clone 函数也可以
class ActionImp:public IAction,public ImplementCreator<ActiomImp> {
// 具体的实现
};
class ObjectFactory : public Singleton<ObjectFactory>{
public:
Implement* create(const char *name)
{
auto it = imps.find(name);
if (it != imps.end())
{
return it->second->clone();
}
return 0;
}
//初始化的时候放入具体的实现
void init()
{
_imps["ActionImp"] = new ActionImp();
}
private:
std::unordered_map<std::string,Implement*> _imps;
}上面的Singleton的代码如下
template<typename T>
class Singleton {
public:
static T* instance()
{
return &o;
}
private:
static T o;
}
template<typename T>
T Singleton<T>::o;以上就是factory 的代码实现了名字与实现的绑定,但是我们如何从配置文件中指定具体的实现呢?