C++ 设计模式——职责链模式

2024-08-31 19:52
文章标签 c++ 设计模式 模式 职责

本文主要是介绍C++ 设计模式——职责链模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • C++ 设计模式——职责链模式
      • 1. 主要组成成分
      • 2. 逐步构建职责链模式
        • 步骤1:定义处理者接口
        • 步骤2:定义抽象处理者
        • 步骤3: 创建具体处理者
        • 步骤4: 配置职责链
      • 3. 备忘录模式 UML 图
        • UML 图解析
      • 4. 单纯与非单纯的职责链模式
        • 4.1 敏感词过滤器父类
        • 4.2 具体过滤器实现
        • 4.3 主函数
      • 5. 职责链模式的优点
      • 6. 职责链模式的缺点
      • 7. 职责链模式的适用场景
      • 总结
      • 完整代码

C++ 设计模式——职责链模式

职责链(Chain Of Responsibility)模式也叫责任链模式,是一种行为型模式,用于将一个请求传递给一个链中的若干对象,哪个对象适合处理这个请求就让哪个对象来处理。职责链看起来与传统数据结构中的“链表”非常类似。

引人“职责链”设计模式的定义(实现意图):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(构成对象链),并沿着这条链传递该请求,直到有一个对象处理它为止。

1. 主要组成成分

  1. 处理器接口(Handler Interface):定义了一个处理请求的接口,通常包含一个方法用于接收或处理请求。这个接口不确定请求的具体处理者。
  2. 具体处理器(Concrete Handlers):实现处理器接口的类。每个处理器会对请求做出处理或者将请求传递给链中的下一个处理者。具体处理器决定了处理请求的条件和方式。
  3. 请求类(Request):通常是包含多个属性的类,这些属性决定了哪个具体处理器应该处理该请求。
  4. 客户端(Client):负责创建处理链,并向链的第一个处理器发送请求。客户端不关心请求如何以及由谁处理,这样做实现了发送者和接收者之间的解耦。

2. 逐步构建职责链模式

以下示例展示了如何实现一个用于处理加薪请求的职责链模式。此示例包含三个不同级别的审批者:部门经理、技术总监和总经理,各自能够处理特定范围的加薪请求。以下是构建职责链模式的详细步骤:

步骤1:定义处理者接口

已定义 RaiseRequest 类封装了加薪请求,其中包括员工姓名和加薪金额。

//加薪请求类
class RaiseRequest
{
public://构造函数RaiseRequest(const string& sname, int salfigure) :m_sname(sname), m_isalfigure(salfigure) {}//获取请求加薪的人员名字const string& getName() const{return m_sname;}//获取请求加薪的数字int getSalFigure() const{return m_isalfigure;}private:string m_sname;      //请求加薪的人员名字int    m_isalfigure; //请求加薪的数字
};
步骤2:定义抽象处理者

定义了一个名为 ParSalApprover 的抽象基类,其中包含一个处理请求的纯虚函数 processRequest 和一个函数 setNextChain 用于设置链中的下一个处理者。

//薪水审批者父类
class ParSalApprover
{
public:ParSalApprover() :m_nextChain(nullptr) {}virtual ~ParSalApprover() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个审批者void setNextChain(ParSalApprover* next){m_nextChain = next;}//处理加薪请求virtual void processRequest(const RaiseRequest& req) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象void sendRequestToNextHandler(const RaiseRequest& req){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象m_nextChain->processRequest(req);}else{//没找到链中的下个对象,程序流程执行这里似乎不应该cout << req.getName() << "的加薪要求为:" << req.getSalFigure() << "元,但无人能够审批!" << endl;}}private:ParSalApprover* m_nextChain; //指向下一个审批者(对象)的多态指针(指向自身类型),每个都指向下一个,就会构成一个职责链(链表)
};
步骤3: 创建具体处理者

创建了三个具体处理者:depManager_SA, CTO_SA, 和 genManager_SA,每个类根据其规则处理请求。

//部门经理子类
class depManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure <= 1000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,部门经理审批通过!" << endl;}else{//自己不能处理,尝试找链中的下个对象来处理sendRequestToNextHandler(req);}}
};//技术总监子类
class CTO_SA :public ParSalApprover
{//处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 1000 && salfigure <= 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,技术总监审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//总经理子类
class genManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,总经理审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};
步骤4: 配置职责链

在主函数中,创建处理者对象,并按逻辑顺序将它们连接起来形成一个链。

int main()
{//(1)创建出职责链中包含的各个对象(部门经理、技术总监、总经理)ParSalApprover* pzzlinkobj1 = new depManager_SA();ParSalApprover* pzzlinkobj2 = new CTO_SA();ParSalApprover* pzzlinkobj3 = new genManager_SA();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pzzlinkobj1排在最前面,pzzlinkobj3排在最后面pzzlinkobj1->setNextChain(pzzlinkobj2);pzzlinkobj2->setNextChain(pzzlinkobj3);pzzlinkobj3->setNextChain(nullptr); //可以不写此行,因为ParSalApprover构造函数中设置了m_nextChain为nullptr//(3)创建几位员工关于加薪的请求(对象)RaiseRequest emp1Req("张三", 15000);//张三要求加薪1.5万RaiseRequest emp2Req("李四", 3500);//李四要求加薪3千5RaiseRequest emp3Req("王二", 800);//王二要求加薪8百//看看每位员工的加薪请求由职责链中的哪个对象(部门经理、技术总监、总经理)来处理,从职责链中排在最前面的接收者(pzzlinkobj1)开始pzzlinkobj1->processRequest(emp1Req);pzzlinkobj1->processRequest(emp2Req);pzzlinkobj1->processRequest(emp3Req);//(4)释放资源delete pzzlinkobj1;delete pzzlinkobj2;delete pzzlinkobj3;return 0;
}

3. 备忘录模式 UML 图

职责链模式 UML 图

UML 图解析

职责链模式的 UML 图中包含3种角色:

  1. Handler (处理者):
    • 作用:定义处理请求的接口(通常为 processRequest),同时也记录了链中下一个处理者的引用(在本例中使用 m_nextChain 来记录)。
    • 实现:在示例中,ParSalApprover 类扮演此角色,提供了设置下一个处理者和处理请求的基本框架。
  2. ConcreteHandler (具体处理者):
    • 作用:实现具体请求的处理逻辑。如果当前处理者无法完全处理请求,则将请求传递给链中的下一个处理者(后继者)。
    • 实现:在示例中,depManager_SACTO_SAgenManager_SA 类是具体处理者。每个类都有条件判断是否能处理请求,不能处理时将请求传递给链上的下一个处理者。
  3. Client (请求者/客户端):
    • 作用:向职责链上的具体处理者对象提交处理请求。客户端负责初始化处理链并触发请求处理过程。
    • 实现:在示例中,主函数 main 执行了客户端的角色。除了提交处理请求,它还负责创建职责链对象并搭建职责链。这部分通常是由客户端完成,因为职责链的结构和顺序可能根据不同的业务场景需要不同的配置。

4. 单纯与非单纯的职责链模式

在设计模式中,职责链模式可以分为两种形式:单纯的职责链模式和非单纯的职责链模式。这两种形式主要区别在于请求在链中的传递方式和处理者的责任范围。非单纯的职责链模式中允许一个请求被某个接收者处理后继续沿着职责链传递,其他处理者仍有机会继续处理该请求,这样的职责链往往也被称为功能链,即便一个请求未被任何处理者对象处理,在非单纯的职责链模式中也是允许的。功能链一般用于权限的多次多重校验、数据的多重检查和过滤等场合。

下面给出这个敏感词过滤器非单纯职责链模式范例(参照前面的范例书写即可)。该过滤器能够把聊天内容中涉及性、脏话、政治内容的关键词寻找出来并用一些其他符号来代替。首先创建敏感词过滤器父类,代码如下:

4.1 敏感词过滤器父类

定义一个抽象基类,其中包含将请求传递给链中下一个处理者的方法。

//敏感词过滤器父类
class ParWordFilter
{
public:ParWordFilter() :m_nextChain(nullptr) {}virtual ~ParWordFilter() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个过滤器void setNextChain(ParWordFilter* next){m_nextChain = next;}//处理敏感词过滤请求virtual string processRequest(string strWord) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象string sendRequestToNextHandler(string strWord){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象return m_nextChain->processRequest(strWord);}return strWord;}
private:ParWordFilter* m_nextChain;
};
4.2 具体过滤器实现

接着,创建敏感词过滤器子类共3个,分别用于过滤性、脏话、政治内容,代码如下:

//性敏感词过滤器子类
class SexyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"性\"敏感词并用XXX来替换!" << endl;strWord += "XXX"; //测试代码,具体的实现逻辑略......return sendRequestToNextHandler(strWord);}
};//脏话词过滤器子类
class DirtyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"脏话\"敏感词并用YYY来替换!" << endl;strWord += "YYY";return sendRequestToNextHandler(strWord);}
};//政治敏感词过滤器子类
class PoliticsWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"政治\"敏感词并用ZZZ来替换!" << endl;strWord += "ZZZ";return sendRequestToNextHandler(strWord);}
};
4.3 主函数

在主函数中创建和配置职责链。

int main()
{  //(1)创建出职责链中包含的各个对象(性敏感词过滤器、脏话词过滤器、政治敏感词过滤器)ParWordFilter* pwflinkobj1 = new SexyWordFilter();ParWordFilter* pwflinkobj2 = new DirtyWordFilter();ParWordFilter* pwflinkobj3 = new PoliticsWordFilter();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pwflinkobj1排在最前面,pwflinkobj3排在最后面pwflinkobj1->setNextChain(pwflinkobj2);pwflinkobj2->setNextChain(pwflinkobj3);pwflinkobj3->setNextChain(nullptr);string strWordFilterResult = pwflinkobj1->processRequest("你好,这里是过滤敏感词测试范例"); //从职责链中排在最前面的接收者(pwflinkobj1)开始,processRequest的参数代表的是聊天内容cout << "对敏感词过滤后的结果为:" << strWordFilterResult << endl;//(3)释放资源delete pwflinkobj1;delete pwflinkobj2;delete pwflinkobj3;return 0;
}

执行结果:

通过与词库比对,在strWord中查找"性"敏感词并用XXX来替换!
通过与词库比对,在strWord中查找"脏话"敏感词并用YYY来替换!
通过与词库比对,在strWord中查找"政治"敏感词并用ZZZ来替换!
对敏感词过滤后的结果为:你好,这里是过滤敏感词测试范例XXXYYYZZZ

从结果可以看到,聊天内容(请求)先经过性敏感词过滤器处理,然后再把处理后的聊天内容(请求)传递给脏话敏感词过滤器,脏话敏感词过滤器处理完后再传递给政治敏感词过滤器,这些过滤器形成了一个链条。链条上的每个过滤器各自承担自己的处理职责,经过多次被处理并被放行传递到下一个过滤器的过程,最终处理结果被返回到strWordFilterResult中。

5. 职责链模式的优点

  • 减少请求的发送者和接收者之间的耦合:发送者和接收者不需要知道彼此的具体细节。
  • 增强了系统的灵活性:可以动态地添加或修改处理链,而不影响其他部分。
  • 增强了给定请求的处理机会:请求可以被多个对象处理,不必绑定到特定的处理者。

6. 职责链模式的缺点

  • 请求可能未被处理:如果链配置不当,请求可能会到达链的末端而未被处理。
  • 性能问题:在某些情况下,由于需要在链上进行多次处理判断,可能会引入性能瓶颈。
  • 调试困难:由于处理过程的动态性,可能难以跟踪请求在链中的传递路径。

7. 职责链模式的适用场景

  1. 多个对象可以处理同一请求:当多个对象都可能对请求进行处理,但具体由哪个对象处理在运行时才确定时,职责链模式提供了一种灵活的处理方式。
  2. 不明确具体接收者:在请求的发送者不需要知道请求的具体接收者是谁的情况下,使用职责链模式可以将发送者和接收者解耦。
  3. 可动态指定处理的顺序:当需要在运行时动态改变请求处理者的顺序或者动态添加新的处理者时,职责链模式能够提供这种灵活性。

总结

职责链模式通过建立一条对象链来处理请求,实现了请求发送者和接收者之间的解耦。它在处理具有不同处理级别的请求时特别有用,如日志记录、异常处理等场景。然而,使用时需要注意避免请求在链中过度传递,以及确保所有请求都能得到适当处理。

完整代码

#include <iostream>
using namespace std;//加薪请求类
class RaiseRequest
{
public://构造函数RaiseRequest(const string& sname, int salfigure) :m_sname(sname), m_isalfigure(salfigure) {}//获取请求加薪的人员名字const string& getName() const{return m_sname;}//获取请求加薪的数字int getSalFigure() const{return m_isalfigure;}private:string m_sname;      //请求加薪的人员名字int    m_isalfigure; //请求加薪的数字
};//-------------------
//薪水审批者父类
class ParSalApprover
{
public:ParSalApprover() :m_nextChain(nullptr) {}virtual ~ParSalApprover() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个审批者void setNextChain(ParSalApprover* next){m_nextChain = next;}//处理加薪请求virtual void processRequest(const RaiseRequest& req) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象void sendRequestToNextHandler(const RaiseRequest& req){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象m_nextChain->processRequest(req);}else{//没找到链中的下个对象,程序流程执行这里似乎不应该cout << req.getName() << "的加薪要求为:" << req.getSalFigure() << "元,但无人能够审批!" << endl;}}private:ParSalApprover* m_nextChain; //指向下一个审批者(对象)的多态指针(指向自身类型),每个都指向下一个,就会构成一个职责链(链表)
};//部门经理子类
class depManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure <= 1000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,部门经理审批通过!" << endl;}else{//自己不能处理,尝试找链中的下个对象来处理sendRequestToNextHandler(req);}}
};//技术总监子类
class CTO_SA :public ParSalApprover
{//处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 1000 && salfigure <= 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,技术总监审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//总经理子类
class genManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,总经理审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//敏感词过滤器父类
class ParWordFilter
{
public:ParWordFilter() :m_nextChain(nullptr) {}virtual ~ParWordFilter() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个过滤器void setNextChain(ParWordFilter* next){m_nextChain = next;}//处理敏感词过滤请求virtual string processRequest(string strWord) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象string sendRequestToNextHandler(string strWord){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象return m_nextChain->processRequest(strWord);}return strWord;}
private:ParWordFilter* m_nextChain;
};//性敏感词过滤器子类
class SexyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"性\"敏感词并用XXX来替换!" << endl;strWord += "XXX"; //测试代码,具体的实现逻辑略......return sendRequestToNextHandler(strWord);}
};//脏话词过滤器子类
class DirtyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"脏话\"敏感词并用YYY来替换!" << endl;strWord += "YYY";return sendRequestToNextHandler(strWord);}
};//政治敏感词过滤器子类
class PoliticsWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"政治\"敏感词并用ZZZ来替换!" << endl;strWord += "ZZZ";return sendRequestToNextHandler(strWord);}
};int main()
{//(1)创建出职责链中包含的各个对象(部门经理、技术总监、总经理)ParSalApprover* pzzlinkobj1 = new depManager_SA();ParSalApprover* pzzlinkobj2 = new CTO_SA();ParSalApprover* pzzlinkobj3 = new genManager_SA();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pzzlinkobj1排在最前面,pzzlinkobj3排在最后面pzzlinkobj1->setNextChain(pzzlinkobj2);pzzlinkobj2->setNextChain(pzzlinkobj3);pzzlinkobj3->setNextChain(nullptr); //可以不写此行,因为ParSalApprover构造函数中设置了m_nextChain为nullptr//(3)创建几位员工关于加薪的请求(对象)RaiseRequest emp1Req("张三", 15000);//张三要求加薪1.5万RaiseRequest emp2Req("李四", 3500);//李四要求加薪3千5RaiseRequest emp3Req("王二", 800);//王二要求加薪8百//看看每位员工的加薪请求由职责链中的哪个对象(部门经理、技术总监、总经理)来处理,从职责链中排在最前面的接收者(pzzlinkobj1)开始pzzlinkobj1->processRequest(emp1Req);pzzlinkobj1->processRequest(emp2Req);pzzlinkobj1->processRequest(emp3Req);//(4)释放资源delete pzzlinkobj1;delete pzzlinkobj2;delete pzzlinkobj3;//(1)创建出职责链中包含的各个对象(性敏感词过滤器、脏话词过滤器、政治敏感词过滤器)ParWordFilter* pwflinkobj1 = new SexyWordFilter();ParWordFilter* pwflinkobj2 = new DirtyWordFilter();ParWordFilter* pwflinkobj3 = new PoliticsWordFilter();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pwflinkobj1排在最前面,pwflinkobj3排在最后面pwflinkobj1->setNextChain(pwflinkobj2);pwflinkobj2->setNextChain(pwflinkobj3);pwflinkobj3->setNextChain(nullptr);string strWordFilterResult = pwflinkobj1->processRequest("你好,这里是过滤敏感词测试范例"); //从职责链中排在最前面的接收者(pwflinkobj1)开始,processRequest的参数代表的是聊天内容cout << "对敏感词过滤后的结果为:" << strWordFilterResult << endl;//(3)释放资源delete pwflinkobj1;delete pwflinkobj2;delete pwflinkobj3;return 0;
}

这篇关于C++ 设计模式——职责链模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124850

相关文章

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)