所谓命令控制模式,就是对应的行为进行封装,通过命令就能控制,你可以理解为linux下指令操作。
比如一个操作包括,A1、A2、.....A10这10步操作,如果某一步失败,那么就进行倒回,如果这10个操作的业务类型各不相同,并且所需要的参数也不尽相同,操作起来就比较困难,如果我能将他们全部封装成指令模式,只通过A1到A10这10个字符串就触发,那么实现起来就容易的多。
对于网络编程,命令控制就变得必不可少了,该模型可以帮你将网络层与业务层完美的管理在一起。
实现约束:
1、每一类业务我需要划分为一个业务入口类,便于统一管理。
2、我有很多类的业务,为了便于扩展,每添加一个业务类,我需要尽量少改动框架内容。
3、我可以将每一个业务入口类的函数定义成一个命令。
4、每一个命令字允许我传入不同的参数列表
基于上述约束,实现起来可能有点困难,所以在此进行梳理一下,分两步进行:
第一步:业务入口类的管理实现
实现原理:
1、模板类静态成员在有调用的情况下,编译器会自动展开。
2、静态成员会在main函数之前进行初始化
3、在每一个业务入口类中,定义一个指定静态函数,在函数中使用模板类,以达到让编译器生成模板类实例的目的;
4、模板类的静态成员初始化为业务类的静态函数地址。
5、静态成员初始化时,让模板类之间形成一个链表
基于以上原理,我们可以实现一个如下图所示的,父类与子类的关系:
第二步:将所有容器的命令字进行汇总
这里相对就比较简单了,直接遍历容器,执行所有的容器函数,将命令字进行汇总。
代码实现:
.h文件:
#include <map>
#include <string>
#include <iostream>
#include <unordered_map>
#include <memory>
#include <functional>
#include "singleton.h"
#include "anyval.h"
#define BEGINE_OPCODEREG(className) public:
static void OpcodeInit() {
COPHandleContainer<className> handle;
#define DEFINE_OPCODE(opcode, funcAddr) MakeFuncEntityNode(funcAddr, opcode, #funcAddr);
#define END_OPCODEREG() } private:
//命令字分发类
class COpcodeDispatch
{
public:
~COpcodeDispatch(void) {};
void Initialize();
void RegisterOpcode(const char* opcode, AnyVar opProc, AnyVar funcName);
//命令字分发
template<typename... ARGS>
void Dispatch(const std::string& opcode, ARGS... args)
{
auto iter = m_opHandle.find(opcode);
if (m_opHandle.end() == iter)
{
return ;
}
AnyVar resolver = iter->second;
std::function<void (ARGS...)> funcPtr = any_cast<std::function<void (ARGS...)>>(resolver);
funcPtr(args...);
}
void Dump();
private:
std::unordered_map<std::string, AnyVar> m_opHandle;
std::unordered_map<std::string, AnyVar> m_opFuncName;
};
typedef Singleton<COpcodeDispatch> COpcodeDispatchAgent;
//该类用于存储所有命令字节点的信息,包括函数地址、函数名称
template <typename T, typename... ARGS>
class CMemFuncEntityNode
{
public:
typedef void (T::*mem_func_type)(ARGS...);
CMemFuncEntityNode(mem_func_type memFunc, const char* memFuncName) :m_memFuncAddr(memFunc), m_memFuncName(memFuncName) {}
void operator()(ARGS...args)
{
T obj;
(obj.*m_memFuncAddr)(args...);
}
//支持Opcode的类,原生支持动态创建
void* DynCreate()
{
return new T;
}
const char* GetMemFuncName()
{
return m_memFuncName[0] == '&' ? m_memFuncName + 1 : m_memFuncName;
}
private:
mem_func_type m_memFuncAddr;
const char* m_memFuncName;
};
template<typename T, typename... ARGS>
void MakeFuncEntityNode(void (T::*mem_func_type)(ARGS...), const char* opcode, const char* memFuncName)
{
auto opNode = std::make_shared<CMemFuncEntityNode<T, ARGS...>>(mem_func_type, memFuncName);
//统一转化成 void (ARGS...) 函数,用anyval包装
std::function<void (ARGS...)> function = [opNode](ARGS... args) {
(*opNode)(args...);
};
std::function<const char* ()> funcName = [opNode]() {
return opNode->GetMemFuncName();
};
COpcodeDispatchAgent::get_instance().RegisterOpcode(opcode, function, funcName);
}
//容器基类,存储所有节点信息及容器节点信息
class COPContainerBase
{
public:
static void Initialize();
protected:
typedef void(*cont_func_type)();
virtual ~COPContainerBase();
//存储容器节点,返回容器头节点
static COPContainerBase*& Head();
//此函数为虚函数,目的是为了让编译器对继承该类并实现该函数的类进行检查
virtual void DoNothing()const;
protected:
cont_func_type m_containtFunc;
COPContainerBase* m_nextContainer;
};
//容器类
template <typename T>
class COPHandleContainer : public COPContainerBase
{
public:
COPHandleContainer(void)
{
}
static COPHandleContainer* GetInstance()
{
//注:此处为单例,如果多次调用,Head()链表将会进入形成循环
static COPHandleContainer<T> containerIns;
return &containerIns;
}
//该函数为虚函数,编译器会进行检查,从而实现对静态变量引用的目的
//所有实例化该模板类的类,都会初始化该静态变量,所以必须实现T::OpcodeInit静态函数
inline void DoNothing()const
{
m_opInstance.DoNothing();
}
private:
struct ContaintInstance
{
ContaintInstance(cont_func_type containtFunc)
{
#ifdef _DEBUG
std::cout << "初始化容器函数" << std::endl;
#endif
COPHandleContainer *container = COPHandleContainer::GetInstance();
container->m_containtFunc = containtFunc;
container->m_nextContainer = Head();
Head() = container;
}
inline void DoNothing()const {}
};
static ContaintInstance m_opInstance;
};
//opcode容器加载
template < typename T >
typename COPHandleContainer<T>::ContaintInstance COPHandleContainer<T>::m_opInstance(T::OpcodeInit);
.cpp文件
#include "opcodedispatch.h"
void COpcodeDispatch::RegisterOpcode(const char* opcode, AnyVar opProc, AnyVar funcName)
{
if (m_opHandle.end() != m_opHandle.find(opcode))
{
throw std::invalid_argument(std::string(opcode) + " : this opcode has already exist!");
}
else
{
m_opHandle.emplace(opcode, opProc);
m_opFuncName.emplace(opcode, funcName);
}
}
void COpcodeDispatch::Initialize()
{
COPContainerBase::Initialize();
}
void COpcodeDispatch::Dump()
{
for(auto item : m_opFuncName)
{
AnyVar resolver = item.second;
std::function<const char* ()> funcPtr = any_cast<std::function<const char* ()>>(resolver);
std::cout << item.first << "-->" << funcPtr() << std::endl;;
}
}
/*********************************************************
COPContainerBase
***********************************************************/
COPContainerBase::~COPContainerBase()
{
}
//存储容器节点,返回容器头节点
COPContainerBase*& COPContainerBase::Head()
{
static COPContainerBase *containerHead = 0;
return containerHead;
}
void COPContainerBase::Initialize()
{
//初始化容器
COPContainerBase* currContainer = Head();
while (currContainer != NULL)
{
(*currContainer->m_containtFunc)();
currContainer = currContainer->m_nextContainer;
}
}
//此函数为虚函数,目的是为了让编译器对继承该类并实现该函数的类进行检查
void COPContainerBase::DoNothing()const
{
}
测试代码:
class TestOpcode
{
BEGINE_OPCODEREG(TestOpcode)
DEFINE_OPCODE("TestFunc", &TestOpcode::Func)
DEFINE_OPCODE("TestFunc2", &TestOpcode::Func2)
END_OPCODEREG()
public:
void Func()
{
std::cout << "TestOpcode Func" << std::endl;
}
void Func2(int a, int b)
{
std::cout << "TestOpcode func2:" << a*b << std::endl;
}
};
int main()
{
COpcodeDispatchAgent::get_instance().Initialize();
COpcodeDispatchAgent::get_instance().Dump();
COpcodeDispatchAgent::get_instance().Dispatch("TestFunc");
COpcodeDispatchAgent::get_instance().Dispatch("TestFunc2", 10, 20);
return 0;
}
输出:
TestFunc2-->TestOpcode::Func2
TestFunc-->TestOpcode::Func
TestOpcode Func
TestOpcode func2:200
来源:oschina
链接:https://my.oschina.net/u/3312209/blog/4292319