使用的模式
责任链
命令
享元
作用
责任链
负责主流程
享元
共享所有处理单元的数据,比如命令枚举和全局处理单元
使用享元,便于处理
不使用享元,便于维护。
命令
替换主流程中的一块
使用场景
不是单一的处理场景,处理场景中长出了分支的情况
A->B->C->D->END
->B1 //A可以到B,B1,B2然后继续处理
->B2->END //处理了B2之后就停止了
A->B->C->D->END
->C1->D->B1 //可以在B之后处理C1,然后C1可以从D跳到B1去
**我们只有一个主处理链就是A->B->C->D->END,其余的你可以理解为可以拆卸的模块可以随便拼装**
解析
责任链:A->B
->C->D
享元:原始数据(以及上一次处理之后的数据):srcData 目标数据(最后用户可以get的数据)dstData
命令:X,Y,Z
enum cmd {
X 0x0001
Y 0x0002
Z 0x0003
N 0x0010
}
void put(srcData)
virtual cmd exec() = 0; //处理接口
void get(dstData)
返回N时,正常执行
在运行到B时,返回一个X,那么替换C执行X。然后根据X的返回命令来继续执行
DEMO
#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
enum CMD {
NORMALL = 0x0000,//正常执行链条
CMD_END = 0x0001,//命令链条结束
END = 0x0002,//责任链结束
HELLO = 0x0100,
WORLD = 0x0101
};
class AbstractHandle
{
public:
virtual ~AbstractHandle() = default;
bool run(const std::string &src,std::string &dst)
{
bool ret = false;
CMD cmd = END;
std::string allSrc = src+dst;//累加输入,上一次的输出将作为下一次的输入
ret = exec(allSrc,dst,cmd);
if(!ret)
return false;
switch (cmd) {
case NORMALL:
if(next)
ret = next->run(allSrc,dst);
break;
case CMD_END:
if(next)
if(next->next)
ret = next->next->run(allSrc,dst);
break;
case END:
break;
default:
if(more.find(cmd) != more.end()) {
more[cmd]->set_next(next);//替换责任链上原来的处理器
ret = more[cmd]->run(allSrc,dst);
}
break;
}
return ret;
}
void set_next(std::shared_ptr<AbstractHandle> next)
{
this->next = next;
}
void add_more(CMD cmd,std::shared_ptr<AbstractHandle> newOne)
{
more[cmd] = newOne;
}
protected:
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) = 0;
std::shared_ptr<AbstractHandle> next = nullptr;
///有两种写法,一种是static作为全部子类公有的,还有一种是某一个子类私有的。
/// 写法一,static。把add_more作为static方法,把more作为全局变量,便于注册和使用
/// 写法二,私密性和针对性更强,便于维护和修改
/// 这里使用的是写法二
std::unordered_map<CMD,std::shared_ptr<AbstractHandle>> more;
};
class N1:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = NORMALL;
return true;
}
};
class N2:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = HELLO;
return true;
}
};
class N3:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = NORMALL;
return true;
}
};
class N4:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = END;
return false;
}
};
class HELLO:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = WORLD;
return true;
}
};
class WORLD:public AbstractHandle
{
virtual bool exec(const std::string &srcData,std::string &dstData, CMD &cmd) final
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
dstData += __PRETTY_FUNCTION__;
cmd = CMD_END;
return true;
}
};
class Handle
{
public:
~Handle()
{
deinit();
}
void init()
{
n1 = std::make_shared<N1>();
n2 = std::make_shared<N2>();
n3 = std::make_shared<N3>();
n4 = std::make_shared<N4>();
hello = std::make_shared<class HELLO>();
world = std::make_shared<class WORLD>();
n1->set_next(n2);
n2->set_next(n3);
n3->set_next(n4);
n2->add_more(HELLO,hello);
hello->add_more(WORLD,world);
}
void run(const std::string &src,std::string &dst)
{
n1->run(src,dst);
}
private:
std::shared_ptr<AbstractHandle> n1 = nullptr;
std::shared_ptr<AbstractHandle> n2 = nullptr;
std::shared_ptr<AbstractHandle> n3 = nullptr;
std::shared_ptr<AbstractHandle> n4 = nullptr;
std::shared_ptr<AbstractHandle> hello = nullptr;
std::shared_ptr<AbstractHandle> world = nullptr;
void deinit()
{
}
};