C++ 九阴真经之命令控制模式

穿精又带淫゛_ 提交于 2020-08-15 10:03:09
     所谓命令控制模式,就是对应的行为进行封装,通过命令就能控制,你可以理解为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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!