C++轻量级代理模式
【摘要】 现有代理模式 C++的代理模式有如下2种: 一、抽象类代理,主要用于通知的场景 代理接口(虚函数)全部放在抽象类中,后面通过派生抽象类的方式生成实现代理类。 1、【注册】代理类将自身对象(代理对象)注册到数据源,数据源保存代理对象的引用 2、【注册】使用方将自身...
现有代理模式
C++的代理模式有如下2种:
一、抽象类代理,主要用于通知的场景
代理接口(虚函数)全部放在抽象类中,后面通过派生抽象类的方式生成实现代理类。
1、【注册】代理类将自身对象(代理对象)注册到数据源,数据源保存代理对象的引用
2、【注册】使用方将自身注册代理类中,代理类保存使用方的引用
3、【数据返回】数据源更新时,通过“接口映射”调用代理对象的接口
4、【数据返回】代理对象检索已注册的使用方,并根据使用方已实现的接口,通知数据
二、函数代理模式,主要用于1对1的请求和返回
代理只实现代理接口,并将代理接口注册到数据源,数据源通过代理接口实现数据下发。
1、【注册】代理类将自身函数地址(代理函数)注册到数据源,数据源保存代理函数的引用
2、【注册】请求方发起请求,传入参数和回调接口,代理方保存回调接口,并向数据源发起请求
3、【数据返回】数据源通过代理函数将数据返回给代理
4、【数据返回】代理遍历函数列表,并通过函数地址返回数据
从上述的两种方案中可以看出两者的使用场景并不一致,代理类主要用于通知类接口,代理函数主要用于1对1的请求。
优点:
1、代理方和使用方完全分离,代理方只处理数据不需要处理业务,业务在抛给对应的使用方
缺点:
1、使用方和代理方代码过于分散,代码分布广,查找阅读困难,也就是代码不够【内聚】
2、对于多使用方的场景使用成本高,不利于管理,需专门构建分发模块,通过分发模块将数据分配给对应的使用方
3、而且存在野指针、空指针风险
4、对于小场景使用成本高,比如:http请求,每个使用http请求的点都需要实现代理函数
总结:老的代理模式有老的代理模式的好处,对于大型工程构建是很好的体验,对于频繁固定(数据接口可能会频繁触发)的模式这种很有用处,对于只发生1次的请求,这种模式使用成本有点高,同时存在存在野指针的风险。
轻量级代理设计
为此,结合Objective-C的block思想,创建一个简单的轻量级代理模式,std::function<lambda>作为轻量级代理,
核心:轻量级代理的核心就是一个字“轻”
1、【注册】使用方调用数据源接口,并将lambda传给数据源,数据源通过std::function保存lambda【std::function是重点】
2、【返回】数据源更新数据时,遍历已存储的lambda,通过lambda直接将数据传给使用方
针对常规代理模式存在的问题,这里都可以解决
1、代码集中,使用方和代理方在一块,可以相关输出数据,是一对一的关系,同时不需要一个新的代理模块,代理和业务完全在一起
2、多使用方时,各使用方独立管理自身逻辑,代码完全分割
3、代码集中,存在野指针和空指针的风险较小
4、成本特别小
举例说明:
设计数据源原型:
class DataSource {
public:
static DataSource *getInstance(); // 单例
void sendRequest(int param, std::function<void(int result)> resultCallBack); // 请求接口
private:
void doRequest(int param, int key); // 处理接口
void finishRequest(int result, int key); // 返回接口
private:
static DataSource instance; // 单例
std::mutex m_mutex; // 锁
int m_key{0}; // key
std::map<int,std::function<void(int result)>> delegates; // 代理列表
};
数据源实现:
DataSource DataSource::instance;
DataSource *DataSource::getInstance()
{
return &instance;
}
void DataSource::sendRequest(int param, std::function<void(int result)> resultCallBack)
{
int key = -1;
{
std::lock_guard<std::mutex> guard(m_mutex);
key = ++m_key;
}
delegates[key] = resultCallBack;
doRequest(param, key);
}
void DataSource::doRequest(int param, int key)
{
std::cout << "doing request for key " << key << std::endl;
finishRequest(param * 10, key);
}
void DataSource::finishRequest(int result, int key)
{
std::cout << "finish request for key " << key << std::endl;
std::function<void(int result)> callBack = delegates[key];
if (callBack) {
callBack(result);
delegates.erase(key);
}
}
使用方发起请求:
int main()
{
int outParam = 10;
DataSource::getInstance()->sendRequest(100, [outParam](int result)->void {
int addTen = outParam + result;
std::cout << "request1 result with add ten = " << addTen << std::endl;
});
DataSource::getInstance()->sendRequest(100, [](int result)->void {
std::cout << "request2 result = " << result << std::endl;
});
}
结果:
std::function实现轻量级代理的原理:https://bbs.huaweicloud.com/blogs/416972
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)