C++ 设计模式——访问者模式

news/2024/9/18 13:40:59/ 标签: c++, 设计模式, 访问者模式

目录

C++ 设计模式——访问者模式

访问者模式(Visitor Pattern)是一种行为设计模式,其目的是将数据结构与数据操作分离,使得在不修改已有程序代码的情况下,可以添加新的操作。这种模式通过定义一个访问者类,来改变一个元素类的执行算法。访问者模式使得你能够在不改变元素类的前提下,定义作用于这些元素的新操作。

引人“访问者”模式的定义(实现意图):提供一个作用于某对象结构中的各元素的操作表示,便可以在不改变各元素类的前提下定义(扩展)作用于这些元素的新操作。

1. 主要组成成分

  1. 抽象访问者(Visitor): 提供一个访问元素的接口,声明了一系列访问具体元素的方法。
  2. 具体访问者(Concrete Visitor): 实现抽象访问者中声明的操作,定义对每个元素的具体处理逻辑。
  3. 元素接口(Element): 声明一个接受访问者的方法(accept)。
  4. 具体元素(Concrete Element): 实现元素接口,通过接受访问者的方式允许访问者对其进行操作。
  5. 对象结构(Object Structure): 能枚举它的元素,可以提供一个高层的接口以允许访问者访问其元素。

2. 逐步构建访问者模式

该示例代码将展示如何实现一个药品管理系统,使用访问者模式来处理不同的操作,如收费、取药和营养建议。

步骤1: 创建元素接口和具体元素

首先,定义一个Medicine类作为所有药品的基类,它包含一个名为accept的方法,该方法用于接受一个访问者对象。然后,创建具体的药品类,如M_asplcrp(阿司匹林肠溶片),M_fftdnhsp(氟伐他汀钠缓释片)和M_dlx(黛力新),它们都继承自Medicine并实现accept方法。

class Visitor; //类前向声明
//药品父类
class Medicine
{
public:virtual void Accept(Visitor* pvisitor) = 0;//这里的形参是访问者父类指针
public:virtual string getMdcName() = 0;  //药品名称virtual float getPrice() = 0;     //药品总价格,单位:元
};//药品:阿司匹林肠溶片
class M_asplcrp : public Medicine
{
public:virtual string getMdcName(){return "阿司匹林肠溶片";}virtual float getPrice(){return 46.8f;    //为简化代码,直接给出药品总价而不单独强调药品数量了,比如该药品医生给开了两盒,一盒是23.4,那么这里直接返回两盒的价格}public:virtual void Accept(Visitor* pvisitor);};
//药品:氟伐他汀钠缓释片
class M_fftdnhsp : public Medicine
{
public:virtual string getMdcName(){return "氟伐他汀钠缓释片";}virtual float getPrice(){return 111.3f;    //三盒的价格}public:virtual void Accept(Visitor* pvisitor);};
//药品:黛力新
class M_dlx : public Medicine
{
public:virtual string getMdcName(){return "黛力新";}virtual float getPrice(){return 122.0f;    //两盒的价格}public:virtual void Accept(Visitor* pvisitor);};//各个药品子类Accept方法的实现体代码
void M_asplcrp::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_asplcrp(this);
}
void M_fftdnhsp::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_fftdnhsp(this);
}
void M_dlx::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_dlx(this);
}
步骤2: 创建抽象访问者和具体访问者

然后,定义Visitor类作为抽象访问者,它包含对每种类型药品的访问方法。接着实现具体访问者类如Visitor_SFRY(收费人员),Visitor_QYRY(取药人员)和Visitor_YYS(营养师),分别定义它们如何处理每种药品。

//访问者父类
class Visitor
{
public:virtual ~Visitor() {} //做父类时析构函数应该为虚函数virtual void Visit_elm_asplcrp(M_asplcrp* pelem) = 0;//访问元素:阿司匹林肠溶片virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem) = 0;//访问元素:氟伐他汀钠缓释片virtual void Visit_elm_dlx(M_dlx* pelem) = 0; //访问元素:黛力新
};//收费人员访问者子类
class Visitor_SFRY : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}virtual void Visit_elm_dlx(M_dlx* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}//返回总费用float getTotalCost(){return m_totalcost;}
private:float m_totalcost = 0.0f;  //总费用
};//取药人员访问者子类
class Visitor_QYRY : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}virtual void Visit_elm_dlx(M_dlx* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}
};//营养师访问者子类
class Visitor_YYS : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){cout << "营养师建议:“多吃粗粮少吃油,可以有效的预防血栓”!" << endl;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){cout << "营养师建议:“多吃蘑菇、洋葱、,猕猴桃,可以有效的降低血脂”!" << endl;}virtual void Visit_elm_dlx(M_dlx* pelem){cout << "营养师建议:“多出去走走呼吸新鲜空气,多晒太阳,多去人多热闹的地方,保持乐观开朗的心情”!" << endl;}
};
步骤3:创建对象结构

接着,定义一个ObjectStructure类来管理药品集合,并允许将访问者应用于这些集合。这个类负责维护药品列表,并提供一个方法来执行访问者的操作。对象结构是连接元素和访问者的桥梁,使得不同的访问者可以对元素集合执行不同的操作。

//对象结构
class ObjectStructure
{
public://增加药品到药品列表中void addMedicine(Medicine* p_mdc){m_mdclist.push_back(p_mdc);}void procAction(Visitor* pvisitor){for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter){(*iter)->Accept(pvisitor);}}
private:list <Medicine*> m_mdclist;  //药品列表
};
步骤4: 客户端使用访问者模式

在客户端代码中,创建ObjectStructure对象,添加药品元素,并创建访问者对象。通过调用ObjectStructure的方法,将访问者应用到所有药品上,以实现具体的功能,如收费、取药或提供营养建议。

int main()
{Visitor_SFRY visitor_sf; //收费人员访问者子类,里面承载着向我(患者)收费的算法M_asplcrp mdc_asplcrp;M_fftdnhsp mdc_fftdnhsp;M_dlx mdc_dlx;//各个元素子类调用Accept接受访问者的访问,就可以实现访问者要实现的功能mdc_asplcrp.Accept(&visitor_sf); //累加“阿司匹林肠溶片”的价格mdc_fftdnhsp.Accept(&visitor_sf);//累加“氟伐他汀钠缓释片”的价格mdc_dlx.Accept(&visitor_sf);     //累加“黛力新”的价格cout << "所有药品的总为:" << visitor_sf.getTotalCost() << ",收费人员收取了我的费用!" << endl;//----Visitor_QYRY visitor_qy; //取药人员访问者子类,里面承载着向我发放药品的算法mdc_asplcrp.Accept(&visitor_qy); //我取得“阿司匹林肠溶片”mdc_fftdnhsp.Accept(&visitor_qy);// 我取得“氟伐他汀钠缓释片”mdc_dlx.Accept(&visitor_qy);     //我取得“黛力新”//-----Visitor_YYS visitor_yys;  //营养师访问者子类,里面承载着为我配置营养餐的算法mdc_asplcrp.Accept(&visitor_yys); //营养师针对治疗预防血栓药“阿司匹林肠溶片”给出的对应的营养餐建议mdc_fftdnhsp.Accept(&visitor_yys);//营养师针对降血脂药“氟伐他汀钠缓释片”给出的对应的营养餐建议mdc_dlx.Accept(&visitor_yys);     //营养师针对治疗神经紊乱药“黛力新”给出的对应的营养餐建议//---------ObjectStructure objstruc;objstruc.addMedicine(&mdc_asplcrp);objstruc.addMedicine(&mdc_fftdnhsp);objstruc.addMedicine(&mdc_dlx);objstruc.procAction(&visitor_yys); //将一个访问者对象(visitor_yys)应用到一批元素上,以实现对一批元素进行同一种(营养方面的)操作return 0;
}

3. 访问者模式 UML 图

<a class=访问者模式 UML 图" />

UML 图解析

访问者模式的 UML图中包含如下5种角色。

  • Visitor (抽象访问者):为对象结构中的每个元素子类(例如M_asplcrpM_fftdnhspM_dlx)声明一个访问操作(以Visit开头的方法)。通过这些操作的名称或参数类型,可以明确知道要访问的元素子类的类型。具体的访问者子类需要实现这些访问操作。此处指的是Visitor类。
  • ConcreteVisitor (具体访问者):实现由抽象访问者声明的每个访问操作。每个操作用于访问对象结构中的一种特定类型的元素。这里指的是Visitor_SFRYVisitor_QYRYVisitor_YYS类。
  • Element (抽象元素):定义了一个Accept方法,该方法通常接受一个指向抽象访问者类型的指针作为形参。这里指的是Medicine类。
  • ConcreteElement (具体元素):实现Accept方法,在该方法中调用访问者子类中的访问操作(以Visit开头的方法),以便访问者能够对元素执行操作。这里指的是M_asplcrpM_fftdnhspM_dlx类。
  • ObjectStructure (对象结构):包含多个元素的集合,用于存储元素对象并提供遍历其内部元素的接口,通常用于对一组元素执行统一操作。

4. 访问者模式的优点

  1. 增加新操作容易:可以通过添加新的访问者类来增加新的操作,这符合开闭原则,允许系统易于扩展和维护。
  2. 聚合操作访问者模式使得可以将相关的操作集中到一个访问者中,而不是分散在各个元素类中,这有助于组织和集中管理相关操作,减少系统的复杂性。
  3. 累积状态:访问者可以在访问元素时累积状态,而不需要将这些状态存储在元素之中,这有助于避免元素类变得臃肿,同时可以轻松地添加新的累积逻辑。

5. 访问者模式的缺点

  1. 破坏封装访问者模式通常需要元素暴露一些原本应为私有的实现细节给访问者,这违反了面向对象的封装原则。
  2. 难以维护:如果经常添加新的元素类,每次添加都需要修改所有访问者类以添加新的访问操作,这可能导致代码难以维护。
  3. 复杂度增加:使用访问者模式会增加系统的复杂度,学习和理解系统的难度增加,特别是在具有大量元素和访问者的系统中。

6. 访问者模式适用场景

  1. 操作频繁变化:当系统的数据结构相对稳定,但操作经常变化时,使用访问者模式可以使这些操作易于修改和扩展。
  2. 需要对复合对象执行多种不相关的操作:当需要对一组对象结构执行很多不相关的操作时,而你又希望避免这些操作“污染”这些对象的类。
  3. 区分多种类型的元素:当一个对象结构包含多种类型的元素,并且你希望对这些元素执行一些依赖于其具体类型的操作时。

总结

在实际应用中,访问者模式特别适用于数据结构相对稳定,但操作经常变化的场景,例如在多种不同类型的对象上执行多种不相关的操作。通过将操作逻辑封装在访问者中,可以保持元素类的简洁并易于管理和扩展。总之,访问者模式是一种非常有用的设计工具,可以有效地帮助开发者管理和扩展复杂系统中的操作。

完整代码

#include <iostream>
#include <list>using namespace std;class Visitor; //类前向声明
//药品父类
class Medicine
{
public:virtual void Accept(Visitor* pvisitor) = 0;//这里的形参是访问者父类指针
public:virtual string getMdcName() = 0;  //药品名称virtual float getPrice() = 0;     //药品总价格,单位:元
};//药品:阿司匹林肠溶片
class M_asplcrp : public Medicine
{
public:virtual string getMdcName(){return "阿司匹林肠溶片";}virtual float getPrice(){return 46.8f;    //为简化代码,直接给出药品总价而不单独强调药品数量了,比如该药品医生给开了两盒,一盒是23.4,那么这里直接返回两盒的价格}public:virtual void Accept(Visitor* pvisitor);};
//药品:氟伐他汀钠缓释片
class M_fftdnhsp : public Medicine
{
public:virtual string getMdcName(){return "氟伐他汀钠缓释片";}virtual float getPrice(){return 111.3f;    //三盒的价格}public:virtual void Accept(Visitor* pvisitor);};
//药品:黛力新
class M_dlx : public Medicine
{
public:virtual string getMdcName(){return "黛力新";}virtual float getPrice(){return 122.0f;    //两盒的价格}public:virtual void Accept(Visitor* pvisitor);};//----------------
//访问者父类
class Visitor
{
public:virtual ~Visitor() {} //做父类时析构函数应该为虚函数virtual void Visit_elm_asplcrp(M_asplcrp* pelem) = 0;//访问元素:阿司匹林肠溶片virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem) = 0;//访问元素:氟伐他汀钠缓释片virtual void Visit_elm_dlx(M_dlx* pelem) = 0; //访问元素:黛力新
};//收费人员访问者子类
class Visitor_SFRY : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}virtual void Visit_elm_dlx(M_dlx* pelem){float tmpprice = pelem->getPrice();cout << "收费人员累计药品“" << pelem->getMdcName() << "”的价格:" << tmpprice << endl;m_totalcost += tmpprice;}//返回总费用float getTotalCost(){return m_totalcost;}
private:float m_totalcost = 0.0f;  //总费用
};//取药人员访问者子类
class Visitor_QYRY : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}virtual void Visit_elm_dlx(M_dlx* pelem){cout << "取药人员将药品“" << pelem->getMdcName() << "”拿给了我!" << endl;}
};//营养师访问者子类
class Visitor_YYS : public Visitor
{
public:virtual void Visit_elm_asplcrp(M_asplcrp* pelem){cout << "营养师建议:“多吃粗粮少吃油,可以有效的预防血栓”!" << endl;}virtual void Visit_elm_fftdnhsp(M_fftdnhsp* pelem){cout << "营养师建议:“多吃蘑菇、洋葱、,猕猴桃,可以有效的降低血脂”!" << endl;}virtual void Visit_elm_dlx(M_dlx* pelem){cout << "营养师建议:“多出去走走呼吸新鲜空气,多晒太阳,多去人多热闹的地方,保持乐观开朗的心情”!" << endl;}
};//各个药品子类Accept方法的实现体代码
void M_asplcrp::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_asplcrp(this);
}
void M_fftdnhsp::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_fftdnhsp(this);
}
void M_dlx::Accept(Visitor* pvisitor)
{pvisitor->Visit_elm_dlx(this);
}//-------------//对象结构
class ObjectStructure
{
public://增加药品到药品列表中void addMedicine(Medicine* p_mdc){m_mdclist.push_back(p_mdc);}void procAction(Visitor* pvisitor){for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter){(*iter)->Accept(pvisitor);}}
private:list <Medicine*> m_mdclist;  //药品列表
};int main()
{Visitor_SFRY visitor_sf; //收费人员访问者子类,里面承载着向我(患者)收费的算法M_asplcrp mdc_asplcrp;M_fftdnhsp mdc_fftdnhsp;M_dlx mdc_dlx;//各个元素子类调用Accept接受访问者的访问,就可以实现访问者要实现的功能mdc_asplcrp.Accept(&visitor_sf); //累加“阿司匹林肠溶片”的价格mdc_fftdnhsp.Accept(&visitor_sf);//累加“氟伐他汀钠缓释片”的价格mdc_dlx.Accept(&visitor_sf);     //累加“黛力新”的价格cout << "所有药品的总为:" << visitor_sf.getTotalCost() << ",收费人员收取了我的费用!" << endl;//----Visitor_QYRY visitor_qy; //取药人员访问者子类,里面承载着向我发放药品的算法mdc_asplcrp.Accept(&visitor_qy); //我取得“阿司匹林肠溶片”mdc_fftdnhsp.Accept(&visitor_qy);// 我取得“氟伐他汀钠缓释片”mdc_dlx.Accept(&visitor_qy);     //我取得“黛力新”//-----Visitor_YYS visitor_yys;  //营养师访问者子类,里面承载着为我配置营养餐的算法mdc_asplcrp.Accept(&visitor_yys); //营养师针对治疗预防血栓药“阿司匹林肠溶片”给出的对应的营养餐建议mdc_fftdnhsp.Accept(&visitor_yys);//营养师针对降血脂药“氟伐他汀钠缓释片”给出的对应的营养餐建议mdc_dlx.Accept(&visitor_yys);     //营养师针对治疗神经紊乱药“黛力新”给出的对应的营养餐建议//---------ObjectStructure objstruc;objstruc.addMedicine(&mdc_asplcrp);objstruc.addMedicine(&mdc_fftdnhsp);objstruc.addMedicine(&mdc_dlx);objstruc.procAction(&visitor_yys); //将一个访问者对象(visitor_yys)应用到一批元素上,以实现对一批元素进行同一种(营养方面的)操作return 0;
}

http://www.ppmy.cn/news/1521626.html

相关文章

【netty系列-09】深入理解和解决tcp的粘包拆包

Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…

【网络安全】漏洞挖掘

漏洞描述 Spring框架为现代基于java的企业应用程序(在任何类型的部署平台上)提供了一个全面的编程和配置模型。 Spring Cloud 中的 serveless框架 Spring Cloud Function 中的 RoutingFunction 类的 apply 方法将请求头中的“spring.cloud.function.routing-expression”参数…

8、Django Admin后台中添加Logo

在项目settings.py文件 # 导入os&#xff0c;并且修改DIRS内容如下所示 import os TEMPLATES [{BACKEND: django.template.backends.django.DjangoTemplates,DIRS: [os.path.join(BASE_DIR, templates/)],APP_DIRS: True,OPTIONS: {context_processors: [django.template.con…

Nginx运维规范及安全配置

1.禁止在location字段对所有请求进行转发 location / {root html;index index.html idindex.htm;proxy_pass http://100.x.x.x:xxx/; }没有对url请求进行过滤&#xff0c;将所有请求转发到后台服务&#xff0c;会导致攻击类的URL被转发到后台&#xff0c;存在安全隐患 禁止使用…

glsl着色器学习(四)

前面讲到已经创建了程序对象&#xff0c;链接到顶点着色器和片段着色器&#xff0c;接着继续。 const positionLoc gl.getAttribLocation(prg, position); const normalLoc gl.getAttribLocation(prg, normal); const texcoordLoc gl.getAttribLocation(prg, texcoord);cons…

数据结构:(LeetCode101)对称二叉树

给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; 树中节点数目在范围…

无需更换摄像头,无需施工改造,降低智能化升级成本的智慧工业开源了。

智慧工业视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。用户只需在界面上…

数理金融工程毕业之后求职应用方向,量化交易方面如何

炒股自动化&#xff1a;申请官方API接口&#xff0c;散户也可以 python炒股自动化&#xff08;0&#xff09;&#xff0c;申请券商API接口 python炒股自动化&#xff08;1&#xff09;&#xff0c;量化交易接口区别 Python炒股自动化&#xff08;2&#xff09;&#xff1a;获取…

国产隔离放大器:增强信号完整性和系统安全性的指南

隔离放大器是电子领域的关键组件&#xff0c;特别是在信号完整性和电气隔离至关重要的应用中。这些放大器隔离输入和输出信号&#xff0c;使它们能够在没有直接电气连接的情况下跨不同系统传输数据。这确保了电路一部分的高压尖峰或噪声不会影响另一部分&#xff0c;从而保护了…

随机森林的知识博客:原理与应用

随机森林&#xff08;Random Forest&#xff09;是一种基于决策树的集成学习算法&#xff0c;它通过组合多棵决策树的预测结果来提升模型的准确性和稳健性。随机森林具有强大的分类和回归能力&#xff0c;广泛应用于各种机器学习任务。本文将详细介绍随机森林的原理、构建方法及…

(C++ STL)容器适配器stack、queue、priority_queue的简单实现与源码

容器适配器stack、queue、priority_queue 一、容器适配器二、deque容器1.deque的原理介绍2.deque的特点3.选择deque作为stack和queue的底层默认容器 三、stack简单实现与源码四、queue简单实现与源码五、priority_queue简单实现与源码 以下代码环境为 VS2022 C。 一、容器适配…

sqli-labs靶场(56-60)

56关 ?id-1)union select 1,2,database()-- 看数据库 ?id-1) union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()-- 看表 ?id-1) union select 1,group_concat(column_name),3 from information_schema.columns wh…

Mysql8 主从复制主从切换(超详细)

文章目录 1 主从复制1.1 实施前提1.2 主节点配置(在192.168.25.91操作)1.3 从节点配置(在192.168.25.92操作)1.4 创建用于主从同步的用户1.5 开启主从同步1.5 主从同步验证 2 主从切换2.1 实施前提2.2 主节点设置只读(在192.168.25.91操作)2.3 检查主从数据是否同步完毕(在192.…

IC 设计前端到后端的流程和 EDA 工具?

IC设计前端也称逻辑设计&#xff0c;后端设计也称物理设计&#xff0c;两者并没有严格的界限&#xff0c;一般涉及到 与工艺有关的设计就是后端设计。 1&#xff1a;规格制定&#xff1a;客户向芯片设计公司提出设计要求。 2&#xff1a;详细设计&#xff1a;芯片设计公司&am…

2024年上海松江启动建筑绿色低碳发展专项检查,共绘城市节能新篇章

2024年9月4日&#xff0c;2024年度松江区建筑工程绿色低碳发展工作专项检查会议正式开展&#xff0c;会议内容主要围绕以下三点&#xff0c; 1、《关于开展 2024年度本市建筑领域绿色低碳发展工作监督检查的通知》宣贯。 2、分项计量、能效测评工作验收要求介绍。 3、专项检…

【初出江湖】分布式之什么是分布式存储?

目录标题 分布式存储分布式存储系统特点分布式存储原理分布式存储的应用场景分布式存储和集中式存储的区别 分布式存储 分布式存储是一种将数据分散存储在多个节点上的存储方式。与传统的集中式存储相比&#xff0c;分布式存储将数据分布在多个节点上&#xff0c;每个节点都可…

2024 年高教社杯全国大学生数学建模竞赛题目-A 题 “板凳龙” 闹元宵

“板凳龙”&#xff0c;又称“盘龙”&#xff0c;是浙闽地区的传统地方民俗文化活动。人们将少则几十条&#xff0c; 多则上百条的板凳首尾相连&#xff0c;形成蜿蜒曲折的板凳龙。盘龙时&#xff0c;龙头在前领头&#xff0c;龙身和龙尾 相随盘旋&#xff0c;整体呈圆盘状。一…

【论文阅读】Single-Stage Visual Query Localization in Egocentric Videos

paper&#xff1a;[2306.09324] Single-Stage Visual Query Localization in Egocentric Videos (arxiv.org) code&#xff1a;hwjiang1510/VQLoC: (NeurIPS 2023) Open-set visual object query search & localization in long-form videos (github.com) 简介 动机&…

Flask中多app应用怎么完成

在Flask中实现多app应用&#xff0c;通常指的是在同一个Flask项目中运行多个相对独立的应用&#xff08;或称为模块、组件&#xff09;。这种需求在大型项目中尤为常见&#xff0c;因为它可以帮助开发者更好地组织代码&#xff0c;提高项目的可维护性和可扩展性。以下将详细阐述…

11.2.软件系统分析与设计-数据库分析与设计

数据库分析与设计 数据库分析与设计的步骤