Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
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 的代码实现了名字与实现的绑定,但是我们如何从配置文件中指定具体的实现呢?

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /