最近在学习设计模式,经常能看到对反射机制的倍加推崇,如反射机制配合工厂方法模式可以有效减少逻辑判断分支存在导致不便维护的情况。所谓的反射的机制,即通过动态地字符串等输入参数为信息入口自动寻址调用相应函数的机制。
比如如下场景
/*****something forehead********/
switch key{
case "调用SQL server数据库":
return new SqlServerFactory();
break;
case "调用MySQL数据库":
return new MySQLFactory();
break;
case "调用Oracle数据库":
return new OracleFactory();
break;
...
default:
error("No matched database info");
在C#中存在的反射机制可以直接通过动态输入的字符串信息自动寻址调用相应函数,省去了静态代码的匹配过程。格式为Assembly.Load(“程序集名称”).CreateInstance(“命名空间.类名称”)
,举个应用例子
using System.Reflection; //C#反射机制使用声明
class DataBaseAccess
{
private static string AssemblyName = "CurrentFileName";
private static string wantedDB = "Oracle";
public static Iuser CreateUser()
{
string ClassName = AssemblyName + "."+db+"Factory";
return (Iuser)Assembly.Load(AssemblyName).CreateInstance(ClassName);
}
...
这样便可以通过输入字符串动态的进行组装和逻辑寻址调用,而不用事先在代码中手动写入所有情况的具体路径和逻辑分支结构,显然对于程序的扩展性有很大的帮助。但很可惜C++暂且不支持反射机制!
C++并不支持反射机制,只能自己实现。如果需要实现字字符串到函数到映射,使用函数指针是一个很直接的逻辑。事先注册好“keystring-function”对应关系,根据字符串就可以调用相应函数了。主要有以下几点:
(1) 可以使用map保存字符从到函数指针到映射。
(2) 工厂模式根据不同到字符串构造不同的类的对象。
通过单例模式建立全局唯一的注册表
#ifndef __CLASSFACTORY_
#define __CLASSFACTORY_
#include <iostream>
#include<string>
#include<map>
//定义函数指针,此处函数指针约定了可以注册的函数的基本形式,
//相比于C#的反射机制的可注册函数的类型无关性还是差了点意思
typedef void* (*create_fun)();
class ClassFactory{
public:
~ClassFactory() {};
//根据类注册时的名字, 创建类实例, 并返回
void* getClassByName(std::string name){
std::map<std::string, create_fun>::iterator it = my_map.find(name);
if (it == my_map.end()) { return NULL; }
create_fun fun = it->second;
if (!fun) { return NULL; }
return fun();
}
//注册类名称与指针函数到映射关系
void registClass(std::string name, create_fun fun){
my_map[name] = fun;
}
//单例模式,不仅仅是提供一个单例静态函数,还需要将无参构造函数给private私有化,这样外部才无法调用new,要生成该class对象,只能通过getInstance()单例函数唯一一条路
static ClassFactory& getInstance(){
static ClassFactory fac;
return fac;
}
private:
ClassFactory() {}; //单例模式的另一个重要特征,私有构造函数,让上面的静态函数成为唯一的创建入口
std::map<std::string, create_fun> my_map;
};
#endif
定义要注册的函数集合
#ifndef __TEST_H
#define __TEST_H
#include <iostream>
class Test{
public:
Test(){ std::cout << "call Test Constructor fun" << std::endl; }
~Test(){ std::cout << "call Test Destructor fun" << std::endl; }
void print(){ std::cout << "call Test print hola fun" << std::endl; }
};
void* create_Test(){
Test *t = new Test();
return (t == NULL)? NULL:t;
}
void* another_func(){
std::cout<<"get inside another_func"<<std::endl;
}
#endif
测试文件
#include "test.h"
#include "class_factory.h"
int main(){
//注册
ClassFactory::getInstance().registClass("Test", create_Test);
ClassFactory::getInstance().registClass("func", another_func);
//获取类对象
Test *t = (Test*)ClassFactory::getInstance().getClassByName("Test");
if (!t){
std::cout << "get instance Test err;" << std::endl;
return 1;
}
t->print();
ClassFactory::getInstance().getClassByName("func");
// delete t;
return 0;
}
当然针对ClassFactory::getInstance().registClass("Test", create_Test);
过于冗长,可以采用宏来改善书写环境
#define REGISTER(className) \
ClassFactory::getInstance().registClass(#className, create_##className)
#define RETRIEVE(className) \
ClassFactory::getInstance().getClassByName(#className)