在构建C++框架时经常用到一项基础技术, 就是根据一个类名称字符串动态创建类对象, 这样可以实现即为彻底的解耦合, 比如常规的基于工厂方法的创建实例代码需要在工厂实现文件中去include各个子类头文件,并需要显式的去调用子类构造函数, 如下代码示例:
#include "A.h"
#include "B.h"
#include "C.h"
Base* Factory::CreateObject()
{
Object* obj = nullptr;
if(xxx)
{
obj = new A();
}
else if(xxx)
{
obj = new B();
}
else
{
obj = new C();
}
return obj;
}
这种写法每加入一个新的子类,都需要修改这个Create入口, 且无法实现配置化
而如果能支持一种根据类名动态创建类实例的能力,则将大大改善
如下示例,className可以通过配置化获取, 不需要显示调用子类的构造函数
Base* b = CreateObject(className);
b->Execute();
实现原理核心元素:
一个管理支持动态创建能力类的工厂ObjectFactory类, 其中核心成员是一个map:
key:类名字符串 -->value:创建该类对象的函数指针
并提供2个核心函数:
1.注册某个类到map RegisterObj(类名字符串, 创建该类的函数指针)
2.创建对象 CreateObj(类名字符串)
类图:
需要支持该能力的类继承Object类, 并注册创建自身实例的静态函数指针到ObjectFactory
可以利用宏定义增加易用性
自动注册时机原理:
利用全局静态变量的初始化在main函数之前的原理, 对于此类支持动态创建的类,都增加一个静态变量初始化时驱动调用注册
static int g_tmp_xxx = ObjectFactory::GetInstance().RegisterObj("ClassName", ClassName::CreateObj);
实现代码包含核心代码+简化实用的宏+单元测试
代码风格基于C++ 11
ObjectFactory.h
#ifndef __OBJECTFACTORY_H__
#define __OBJECTFACTORY_H__
#include
ObjectFactory.cpp
#include "ObjectFactory.h"
using namespace std;
ObjectFactory& ObjectFactory::GetInstance()
{
static ObjectFactory instance_;
return instance_;
}
int ObjectFactory::RegisterObj(const std::string& className, ObjCreator objCreator)
{
creatorMap_.insert(make_pair(className, objCreator));
return 0;
}
Object* ObjectFactory::CreateObj(const std::string& className)
{
auto it = creatorMap_.find(className);
if(it == creatorMap_.end())
{
return nullptr;
}
return it->second();
}
ObjectFactory::ObjectFactory()
{
}
ObjectFactory::~ObjectFactory()
{
}
CreateObj.h 这是增加易用性宏
CREATE_OBJECT提供了模板版本增加类型转换易用性
#ifndef __CREATEOBJ_H__
#define __CREATEOBJ_H__
#include "ObjectFactory.h"
#define DECLARE_DYNAMIC_CREATE(CLASS_NAME) \
static Object* CreateObj(); \
std::string GetClassName() const override;
#define DYNAMIC_CREATE(CLASS_NAME) \
Object* CLASS_NAME::CreateObj() \
{ \
return static_cast
测试代码
Person.h 支持动态创建声明DECLARE_DYNAMIC_CREATE
#ifndef __PERSON_H__
#define __PERSON_H__
#include "CreateObj.h"
#includeclass Person : public Object
{
public:
DECLARE_DYNAMIC_CREATE(Person)
virtual void Do();
void IntroduceSelf();
std::string name_;
int age_;
};
#endif
Person.cpp
支持动态创建实现宏 DYNAMIC_CREATE
#include "Person.h"
#includeusing namespace std;
DYNAMIC_CREATE(Person)
void Person::IntroduceSelf()
{
cout<< "I am "<Student.h
#ifndef __STUDENT_H__
#define __STUDENT_H__
#include "Person.h"
class Student : public Person
{
public:
DECLARE_DYNAMIC_CREATE(Student)
void Do() override;
};
#endif
Student.cpp
#include "Student.h"
#include "Person.h"
#includeusing namespace std;
DYNAMIC_CREATE(Student)
void Student::Do()
{
cout<< "I am a student, I am learning"<< endl;
}
测试用例
没有引入Student.h, 但可以通过类名字符串"Student"创建实例执行
#include "gtest.h"
#include "Person.h"
#include "CreateObj.h"
#includeusing namespace std;
class CreateObjTest : public ::testing::Test
{
};
void PersonExecute(Person* p)
{
p->name_="wangliang";
p->age_ = 18;
p->IntroduceSelf();
p->Do();
}
TEST_F(CreateObjTest, TestCreatePerson)
{
Person* p = CREATE_OBJECT("Person");
if(p == nullptr)
{
GTEST_FAIL();
return;
}
EXPECT_TRUE(p->GetClassName() == "Person");
PersonExecute(p);
}
TEST_F(CreateObjTest, TestCreateStudentAsPerson)
{
Person* p = CREATE_OBJECT("Student");
if(p == nullptr)
{
GTEST_FAIL();
return;
}
EXPECT_TRUE(p->GetClassName() == "Student");
PersonExecute(p);
}
运行效果:
![](/upload/otherpic42/797fbc068adf4e7480a647d039c46b4d.jpg)
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
新闻标题:C++框架技术-根据类名动态创建类对象-创新互联
文章链接:http://bjjierui.cn/article/hjoss.html