【君正T31开发记录】8.了解rtsp协议及设计模式

前边搞定了驱动,先不着急直接上手撸应用层的代码,先了解一下大致要用到的东西。
设计PC端先用vlc rtsp暂时H264编码(vlc好像不支持h265,这个后边我试试)的视频流,先需要支持上rtsp server,了解rtsp协议是必须的,然后设计这个server,带入一些设计模式的思想优化整体框架设计。

RTSP协议

实时流传输协议(Real-Time Streaming Protocol,简称RTSP)是一种应用层协议。用于C/S模型,基于文本。其网络包不带具体流媒体负载,只用于建立流媒体传输管道及控制流媒体传输,具体流媒体负载一般用RTP (Real-time Transport Potocol) 实时传输协议传输实时数据的。协议文档RFC2326供参考

交互

请求-响应 模型,client发起请求,server返回响应。

流程:

  • 初始化会话:client发送控制请求,server响应并建立会话,返回session;
  • 控制:client请求流媒体资源的描述,设置传输参数等;
  • 传输:建立RTP传输信道,通过RTP传输流媒体负载。

RTSP的方法相关:
在这里插入图片描述
文档描述了RTSP的方法,用于流媒体传输的控制,标记了必须、可选、建议三种类型,必须的method在传输控制中必须实现。
在摄像头传输中,摄像头模组端作为server,遵循标准server状态机状态转换要求:
在这里插入图片描述
定制我们自己的状态机(摄像头实时录像,不支持回放、暂停),根据需要配置可选method:

statemethodnext state
initSETUPReady
TEARDOWNInit
ReadyPLAYPlaying
SETUPReady
TEARDOWNInit
PlayingPLAYPlaying
TEARDOWNInit
SETUPPlaying

协议字段

了解下具体协议字段:

  • OPTIONS(必须)
    OPTIONS可以在任何时候发出,不影响server状态,这是文档所说,应该就是类似于心跳包保活机制用。
    在这里插入图片描述
  • DESCRIBE(建议)
    主要是client将rtsp 的 URL传到server,server根据URL找到具体媒体资源,也就是说client可以通过不同的URL从同一个server拉出不同的媒体资源,比如从同一台摄像头根据不同的URL区分主码流、辅码流。
    server回复包含媒体的具体信息,client通过这些信息设置播放参数,包括编码类型、帧率啥的。

在这里插入图片描述

  • ANNOUNCE(可选)
    非rtsp协议标准的一部分,client向server发送SDP描述,是client控制server的手段,常用于推流通知、更新设备状态。可定制。
    在这里插入图片描述
  • SETUP(必需)
    client向server确定媒体的具体传输方法,根据URL识别。client请求包含server媒体流的URL和接收RTP的端口及RTCP的端口;server回复应答机补充发送端口。server不支持的URL回复 错误码455-method not valid in this state。
    在这里插入图片描述
  • PALY(必需)
    client通过 PLAY 请求来播放一个或全部媒体流,PLAY 请求可以发送一次或多次,发送一次时,URL 为包含所有媒体流的地址,发送多次时,每一次请求携带的 URL 只包含一个相应的媒体流。PLAY 请求中可指定播放的 range,若未指定,则从媒体流的开始播放到结束,如果媒体流在播放过程中被暂停,则可在暂停处重新启动流的播放。
    在这里插入图片描述
    在这里插入图片描述
  • PAUSE(建议)
    暂停正在播放的媒体
    在这里插入图片描述
  • TEARDOWN(必需)
    结束会话请求,该请求会停止所有媒体流,并释放服务器上的相关会话数据。
    在这里插入图片描述
  • GET_PARAMETER(可选)
    client通过发送这个命令,申请询问server相关媒体参数
    在这里插入图片描述
  • SET_PARAMETER(可选)
    client通过这个命令修改server媒体参数。
    在这里插入图片描述
  • REDIRECT(可选)
    server向client发送的命令,用于场景:1.负载均衡,server引导client连接低负载server;2.迁移服务器,引导client迁移到新的服务器地址;3.网络拓扑变化,引导client重新适应新网络
    在这里插入图片描述
  • RECORD(可选)
    client通知server端开始录像,储存在server端,非client记录当前播放的媒体。
    在这里插入图片描述

状态码相关

细节还是查询文档比较好,成功回复状态码和回复格式基本是确定的-200
在这里插入图片描述

设计模式(带C++代码示例)

参考原文,敲一遍代码深入理解一下。

创建型

关注对象的创建过程,旨在隐藏创建逻辑以提高代码灵活性可维护性

1.单例模式

确保一个类只有一个实例,并提供一个全局访问点。(全局只有一个实例,中心思想是私有构造函数,使对象创建只有一个入口)

代码:

#include <iostream>
using namespace std;class Singleton{private:Singleton(){//私有构造函数 cout << "Singleton()" << endl;};//私有构造函数 static Singleton* instance;static int cnt;public:static Singleton* getInstance(){//静态方法,获取实例 if(instance==nullptr){instance = new Singleton();}return instance; }
};Singleton* Singleton::instance = nullptr;
int Singleton::cnt = 0;int main(){//Singleton* normal = new Singleton(); //不支持直接实例化 Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();//s1 s2指向同一个实例 return 0;
}

运行:
在这里插入图片描述

2.工厂方法模式

定义一个创建对象的接口,但是是由子类确定实例化哪一个类。(不同的工厂生产不同的产品,工厂各自的产品方法各自实现)

代码:

#include<iostream>
using namespace std;//抽象产品 class Product {public:virtual void operation() = 0;}; //具体产品class ProductA : public Product{public:void operation() override{cout << "product A" << endl;}}; class ProductB : public Product{public:void operation() override{cout << "product B" << endl;}};//抽象工厂class Factory{public:virtual Product* factoryMethod() = 0;}; //具体工厂class FactoryA : public Factory{public:Product* factoryMethod() override{return new ProductA;  	}};class FactoryB : public Factory{public:Product* factoryMethod() override{return new ProductB;  	}}; int main(){Factory* factoryA = new FactoryA();Product* productA = factoryA->factoryMethod();productA->operation();Factory* factoryB = new FactoryB;Product* productB = factoryB->factoryMethod();productB->operation();delete factoryA;delete productA;delete factoryB;delete productB;return 0;}

运行:
在这里插入图片描述

3.抽象工厂模式

提供一个创建一系列相关或互相依赖对象的的接口,而无需指定它们具体的类。(工厂方法抽象,具体工厂实现各自的产品,创建产品的路径一致)

代码:

#include<iostream>
using namespace std;//抽象产品 
class ProductA{public:virtual void operation() = 0;
};
class ProductB{public:virtual void operation() = 0;
};//具体产品
class ConProductA : public ProductA {public:void operation() override{cout << "concreate productA" << endl;}
};  class ConProductB1 : public ProductB {public:void operation() override{cout << "concreate productB1" << endl;}
};
class ConProductB2 : public ProductB {public:void operation() override{cout << "concreate productB2" << endl;}
}; //抽象工厂
class Factory{public:virtual ProductA* createA() = 0;virtual ProductB* createB() = 0;
}; //具体工厂
class ConFactory1 : public Factory{public:ProductA* createA() override{return new ConProductA;}ProductB* createB() override{return new ConProductB1;}
}; 
class ConFactory2 : public Factory{public:ProductA* createA() override{return new ConProductA;}ProductB* createB() override{return new ConProductB2;}
}; int main()
{Factory* factory1 = new ConFactory1;ProductA* a1 = factory1->createA();ProductB* b1 = factory1->createB();a1->operation();b1->operation();Factory* factory2 = new ConFactory2;ProductA* a2 = factory2->createA();ProductB* b2 = factory2->createB();a2->operation();b2->operation();delete factory1;delete a1;delete b1;delete factory2;delete a2;delete b2;return 0;
}

运行:
在这里插入图片描述

4.建造者模式

将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表
示。

代码:

#include <iostream>
using namespace std;//产品 
class Product{public:void setParam(const string& str){param = str;}void show(){cout << param << endl;}private:string param;
};//抽象建造者 
class Builder{public:virtual void buildSet() = 0;virtual Product* build() = 0;
};//具体建造者 
class ConBuilder : public Builder{public:ConBuilder(){product = new Product;};void buildSet() override{product->setParam("product1");}Product* build() override{return product;};private:Product* product;
};
class ConBuilder2 : public Builder{public:ConBuilder2(){product = new Product;};void buildSet() override{product->setParam("product2");}Product* build() override{return product;};private:Product* product;
};
//指挥者,调用具体建造过程 
class Director{public:void construct(Builder* builder){builder->buildSet();}
}; int main(){Director* director = new Director();Builder* b1 = new ConBuilder();director->construct(b1);	Product* p1 = b1->build();p1->show();Builder* b2 = new ConBuilder2();director->construct(b2);Product* p2 = b2->build();p2->show();delete director;return 0;
}

运行:
在这里插入图片描述

5.原型模式

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
实现:定义一个原型接口,具体原型类实现该接口并clone自身方法。
代码:

#include <iostream>
using namespace std;//抽象原型接口类 
class Prototype{public:virtual Prototype* clone() = 0;void setVal(int val){this->val = val;}void show(){cout << val << endl;}private:int val;
};//浅拷贝方法实现原型克隆 
class ConPrototype : public Prototype{public:ConPrototype(int val){setVal(val);}Prototype* clone(){return (Prototype*)this;}
};
class ConPrototype2 : public Prototype{public:ConPrototype2(int val){setVal(val);}Prototype* clone(){return new ConPrototype2(*this);}
};
//深拷贝实现原型克隆 int main(){Prototype* p1 = new ConPrototype(3);p1->show();//克隆 Prototype* p2 = p1->clone();p2->show();Prototype* p3 = new ConPrototype(4);p3->show();//克隆 Prototype* p4 = p1->clone();p4->show();return 0;
}

运行:
在这里插入图片描述

结构型

关注类和对象的组合,旨在通过继承和组合实现更大的灵活性可拓展性

1.适配器模式

将一个类的接口转换成客户希望的另一个接口,使得原本由于接口而不兼容的那些类可以一起工作。

代码:

#include <iostream>
using namespace std;//目标接口
class Target{public:virtual void targetTodo() = 0;
};//需要适配的类 
class LibClass{public:void todo(){cout << "do something" << endl;}
};//适配器类
class Adapter : public Target{public:void targetTodo() override{lib.todo();}private:LibClass lib;
}; int main(){Target* target = new Adapter;target->targetTodo();//通过适配器类直接访问目标接口 return 0;
}

实现:
在这里插入图片描述

2.桥接模式

将抽象部分与它的实现部分分离,使得他们可以独立变化。
代码:

#include <iostream>
#include <memory>
using namespace std;//实例说明,以不同的操作系统为例 
//抽象接口,假定一个需要跨操作系统的接口
class  TargetPlat{public:virtual void targetTodo() = 0;
};//Linux实现
class Linux : public TargetPlat{public:void  targetTodo() override {cout << "linux do" << endl;}
}; 
//Windows实现 
class Win : public TargetPlat{public:void  targetTodo() override {cout << "win do" << endl;}
};//桥
class Bridge{protected:TargetPlat* plat;public:Bridge(TargetPlat* plat){this->plat = plat;}virtual	void func1() = 0;
};//一个需要跨平台是具体功能 
class Func : public Bridge{public:Func(TargetPlat* plat) : Bridge(plat){}void func1() override {cout << "func1" << endl;plat->targetTodo();}
};int main(){unique_ptr<TargetPlat> plat = make_unique<Linux>();unique_ptr<Bridge> birdge = make_unique<Func>(plat.get());birdge->func1();//通过桥,将具体动作映射到Linux return 0;
}

运行:
在这里插入图片描述

3.组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
代码:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;//定义抽象组件基类
class Component{public:virtual void operation() = 0;//业务
};//业务实现
class Leaf : public Component{private:string leafName;public:Leaf(const string& str) : leafName(str){}void operation() override{cout << leafName << "-->operation" << endl;}
};//组合类,对子组件管理
class Compsite : public Component{public:void operation() override{cout << "compsite operation" << endl;for(Component* c : children){c->operation();}}void add(Component* component){//子组件添加接口 children.push_back(component);}void remove(Component* component){//子组件移除接口for (vector<Component*>::iterator it = children.begin(); it<children.end(); it++){if (*it == component){children.erase(it);}}}private:vector<Component*> children;//存储业务子组件 
};int main(){//新建两个叶子子组件,各自实现各自功能shared_ptr<Component> l1 = make_shared<Leaf>("leaf1");shared_ptr<Component> l2 = make_shared<Leaf>("leaf2");shared_ptr<Compsite> c = make_shared<Compsite>();//组合节点//添加子操作到组合节点 c->add(l1.get());c->add(l2.get());c->operation();cout << "*******************" << endl;shared_ptr<Compsite> root = make_shared<Compsite>();//创建更上层的节点shared_ptr<Component> l3 = make_shared<Leaf>("leaf3");root->add(l3.get());root->add(c.get());root->operation();return 0;
}

运行:
在这里插入图片描述

4.装饰模式

动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。
代码:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;//定义一个控制类抽象组件基类
class Control{public:virtual void operation() = 0;//业务
};//控制业务实现组件 
class SpecControl : public Control{public:void operation() override{cout << "SpecControl operation" << endl;}
};//创建装饰者基类 
class Decorator : public Control{public:Decorator(Control* ctrl) : ctrl(ctrl){}virtual void operation(){ctrl->operation();//虚函数,具体控制动作看具体对象 }	private:Control* ctrl; 
};//实现具体装饰者
class  Decorator1 : public Decorator{public:Decorator1(Control* ctrl) : Decorator(ctrl){}virtual void operation(){Decorator::operation();cout << "add Decorator1 self operation" << endl;//在父类基础上添加自己的实现 }
};
class  Decorator2 : public Decorator{public:Decorator2(Control* ctrl) : Decorator(ctrl){}virtual void operation(){Decorator::operation();cout << "add Decorator2 self operation" << endl;}
};int main(){shared_ptr<Control> ctrl = make_shared<SpecControl>();//创建普通控制类 shared_ptr<Control> d1 = make_shared<Decorator1>(ctrl.get());//在普通类基础上,创建有Decorator1自己方法的实例 d1->operation();cout << "*********************" << endl;shared_ptr<Control> d2 = make_shared<Decorator2>(ctrl.get());d2->operation();cout << "*********************" << endl;shared_ptr<Control> d3 = make_shared<Decorator2>(d1.get());//在d1已添加Decorator1方法的基础上,再添加Decorator2方法 d3->operation();return 0;
}

运行:
在这里插入图片描述
适用场景:

  • 需要动态添加功能的场景:如图形控件,动态加很多边框、拖拉条等控件;
  • 避免类膨胀:组合型功能实现,避免大量子类继承;
  • 场景组合类:对象功能需要动态组合,装饰者可以灵活组合大量功能;
  • 开闭源原则
5.外观模式

为子系统中的一组接口提供一个一致的界面,外观模式定义一个高层接口,这个接口使得这一子系统更容易使用。
代码:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;//存在多个子系统
class SubSystem1{public:void method(){cout << "SubSystem1 method" << endl;}
}; 
class SubSystem2{public:void method(){cout << "SubSystem2 method" << endl;}
}; //外观类,融合子系统
class Facade{private:SubSystem1* sys1;SubSystem2* sys2;public:Facade(){sys1 = new SubSystem1;sys2 = new SubSystem2;}~Facade(){delete sys1;delete sys2;}void operation(){sys1->method();sys2->method();}
};int main(){Facade f;f.operation();return 0;
}

运行:
在这里插入图片描述
适用场景:

  • 简化复杂系统:融合多个子系统功能,提供一致性访问接口;
  • 封装遗留代码:将老接口封装在一起,简化调用过程;
  • 降低耦合:有统一调度接口的前提下,不通过class封装子系统,有灵活性,耦合度低。
6.享元模式

运用共享技术,有效支持大量细粒度的对象。
代码:典型运用为下棋

#include <iostream>
#include <memory>
#include <map>
using namespace std;enum Color//颜色 
{white,black
};struct Position//位置 
{int x;int y;Position(int x, int y) : x(x),y(y){}
};//棋子绘制 
class Piece{private:Color color;public:Piece(Color color) : color(color){}void draw(Position pos){if (color == white)cout << "dram white at(" << pos.x << ":" << pos.y << ")" << endl;elsecout << "dram black at(" << pos.x << ":" << pos.y << ")" << endl;}	
};//享元工厂,批量生产棋子 
class PieceFac{public:Piece* getFlyWight(Color color){map<Color, Piece*>::iterator it = flyWightMap.find(color);if(it == flyWightMap.end()){shared_ptr<Piece> tmpP = make_shared<Piece>(color);flyWightMap.insert(make_pair(color,tmpP.get()));return tmpP.get();}else{return it->second;} }private:map<Color, Piece*> flyWightMap;
}; int main(){//批量生成不同位置的黑白棋 unique_ptr<PieceFac> fac = make_unique<PieceFac>();Piece* p1 = fac->getFlyWight(white);p1->draw(Position(2,3));Piece* p2 = fac->getFlyWight(black);p2->draw(Position(2,4));Piece* p3 = fac->getFlyWight(black);p3->draw(Position(3,6));return 0;
}

运行:
在这里插入图片描述

7.代理模式

为其他对象提供一种代理,用以控制这个对象的访问。
代码:

#include <iostream>
#include <memory>
#include <map>
using namespace std;//抽象基类 
class Subject{public:virtual void request() = 0;
};//被代理目标1
class Subject1 : public Subject{public:void request(){cout << "Subject1 request" << endl;}
};
//被代理目标2
class Subject2 : public Subject{public:void request(){cout << "Subject2 request" << endl;}
};//代理类
class Proxy : public Subject{private:Subject* subject;public:Proxy(Subject* subject) : subject(subject){}virtual void request(){subject->request();}
};int main(){unique_ptr<Subject1> sub1 = make_unique<Subject1>();unique_ptr<Subject2> sub2 = make_unique<Subject2>();unique_ptr<Proxy> proxy = make_unique<Proxy>(sub1.get());//代理访问 Subject1proxy->request();unique_ptr<Proxy> proxy2 = make_unique<Proxy>(sub2.get());//代理访问 Subject2proxy2->request();return 0;
}

运行:
在这里插入图片描述

行为型

关注对象之间的通信,旨在通过定义对象间的交互以提高系统灵活性可维护性

1.责任链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
代码:

//典型责任链-流程审批 
#include <iostream>
#include <memory>
using namespace std;//定义处理者接口,定义一个流程请求
class Request{public:int level;Request(int level) : level(level){}void request(){cout << "request" << endl;	};
};//审批者基类
class  Approve{protected:void toNext(Request* req){//交给下一级处理 if(m_next != nullptr){//存在下一级审批 m_next->processRequest(req);}else{//没有下一级审批者 cout << "nobody can do" << endl;}}public:void setNext(Approve* next){m_next = next;}//链接下一个审批者virtual void processRequest(Request* req) = 0;//本层级处理private:Approve* m_next;
};//创建具体审批者,假定两级审批关系
class  ApproveLow : public Approve{void processRequest(Request* req){if(req->level <100 ){//假定低级处理者智能处理小于100权值的任务 cout << "deal by ApproveLow" << endl;}else{//大于权限的,给下一级审批者 toNext(req);} }
};
class  ApproveHigh : public Approve{void processRequest(Request* req){if(req->level <300 ){//假定低级处理者智能处理小于100权值的任务 cout << "deal by ApproveHigh" << endl;}else{//大于权限的,给下一级审批者 toNext(req);} }
};int main(){unique_ptr<Approve> low = make_unique<ApproveLow>();unique_ptr<Approve> high = make_unique<ApproveHigh>();//两个具体审批者实例 low->setNext(high.get()); //建立审批链,low->highRequest r1(60);Request r2(120);Request r3(320);//三个集体审批请求,需要审批权限cout << "r1:60 req" << endl;low->processRequest(&r1);cout << "r1:120 req" << endl;low->processRequest(&r2);cout << "r1:320 req" << endl;low->processRequest(&r3);//统一递交给最低级审批者return 0; 
}

运行:
在这里插入图片描述

2.命令模式

将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行初始化。
代码:

#include <iostream>
#include <memory>
using namespace std;class Receiver;
//命令基类
class Commond{public:virtual void setRec(Receiver* rec) = 0;virtual void execute() = 0;
}; //命令接收者基类
class Receiver{public:virtual void receiveTodo() = 0;
}; 
//具体命令接收者
class Receiver1 : public Receiver{void receiveTodo() override{cout << "Receiver1 get cmd, to do" << endl;}
};
class Receiver2 : public Receiver{void receiveTodo() override{cout << "Receiver2 get cmd, to do" << endl;}
}; //实现命令
class ConCommond : public Commond{private:Receiver* rec;public:ConCommond(Receiver* rec) : rec(rec){}void execute() override{rec->receiveTodo();}void setRec(Receiver* rec) override{this->rec = rec;}
};//创建调用者
class Invoker{private:Commond* cmd;public:Invoker(Commond* cmd) : cmd(cmd){}void executeCmd(){cmd->execute();}
}; int main(){unique_ptr<Receiver> rec = make_unique<Receiver1>();unique_ptr<Commond> cmd = make_unique<ConCommond>(rec.get());Invoker inv(cmd.get());inv.executeCmd();//调用者具体执行 //更换命令接收者unique_ptr<Receiver> rec2 = make_unique<Receiver2>();cmd->setRec(rec2.get());inv.executeCmd();return 0;
}

运行:
在这里插入图片描述

3.解释器模式

给定一个语言,定义它的语法的实现,并定义一个解释器用于调用具体实现。
代码:

//解释器模型典型--计算器,为了简单,暂时只做加法 
#include <iostream>
#include <memory>
#include <stack>
#include <sstream>
using namespace std;//计算器表达式基类 
class Expression{public:virtual ~Expression(){}virtual int interpret() = 0;
};
//数字表达式类
class NumExpression : public Expression{public:NumExpression(int num) : num(num){}int interpret() override {return num;}private:int num;
};
//符号表达式,这里仅加法 
class AddExpression : public Expression{public:~AddExpression(){delete left;delete right;}AddExpression(Expression* l, Expression* r) : left(l),right(r){}int interpret(){return left->interpret() + right->interpret();}private:Expression* left;Expression* right;
}; //解释器类
class  Context{public:Expression* exaluate(const string& expression){stack<Expression*> st;stringstream ss(expression);string token;while(getline(ss,token, ' ')){if (token == "+"){cout << "this +" << endl;Expression* addExp = new AddExpression(nullptr,nullptr);st.push(addExp);}else if(token == "="){cout << "this =" << endl;Expression* r = st.top(); st.pop();delete st.top(); st.pop();//推出符号,这个已经知道是+ Expression* l = st.top(); st.pop();Expression* addExp = new AddExpression(l,r);st.push(addExp);}else{int num = stoi(token);cout << "this " << num << endl;Expression* numExp = new NumExpression(num);st.push(numExp);}}return st.top();}};int main(){Context con;shared_ptr<Expression> exp(con.exaluate("2 + 4 ="));int res = exp->interpret();cout << "result:" << res << endl;return 0;
}

运行:
在这里插入图片描述

4.迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象内部表示。
代码:

//典型实现--STL的迭代器,这里实现一个简单的string使用迭代器 
#include <iostream>
#include <string.h>
using namespace std;class StringBase{public:virtual int getSize() = 0;virtual char getItem(int pos) = 0;virtual int begin() = 0;virtual int end() = 0;
};//实现迭代器
class Myiterator{public:Myiterator(StringBase& str) : str(str){}Myiterator& operator ++(){//基础向后移动,前置运算符 pos++;return *this;}char operator *(){//取值 return str.getItem(pos);}void operator =(int a){pos = a;}bool operator <=(int other){return pos <= other;}private:StringBase& str;int pos;//记录位置 
};//String容器实现 
class String : public StringBase{private:char *str;int size;public:String(const char *str){size = strlen(str);this->str = new char[size];memcpy(this->str, str, size);} ~String(){delete[] this->str;}int getSize() override{return size;}char getItem(int pos) override{return str[pos];}int begin() override{return 0;}int end() override{return size;}
};int main(){String str("test str");Myiterator it(str);for(it=str.begin();it<=str.end();++it){//使用迭代器 cout << *it << endl;}return 0;
}

运行:
在这里插入图片描述

5.中介者模式

用一个中介对象来封装一系列对象的交互,中介者使得各个对象不需要显式相互引用,实现解耦,且可以独立改变它们之间的交互。
代码:

//创建两个测试类,通过中介者实现通信 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;class PeopleBase;
//抽象中介 
class AbstractMediator{public:virtual void registerPeople(PeopleBase* people) = 0;//给中介介绍peoplevirtual void sendMsg(const string& msg, PeopleBase* people) = 0;//中介传送消息 
};
//抽象测试类
class PeopleBase{protected:AbstractMediator* mediator;//中介 public:PeopleBase(AbstractMediator* mediator) : mediator(mediator){}virtual void sendMsg(const string& msg) = 0;virtual void receiveMsg(const string& msg) = 0;
}; //中介
class ConMediator : public AbstractMediator{private:vector<PeopleBase*> peoples;//存放有中介需求的元素 public:void registerPeople(PeopleBase* people) override{peoples.push_back(people);}void sendMsg(const string& msg, class PeopleBase* people) override{for(PeopleBase* p : peoples){if(p != people){p->receiveMsg(msg);}}}
}; //测试类
class People : public PeopleBase{private:string name;public:People(AbstractMediator* mediator, string name) : PeopleBase(mediator),name(name){}void sendMsg(const string& msg) override{mediator->sendMsg(msg, this);}void receiveMsg(const string& msg) override{cout << name << " receive msg:" << msg << endl;}
};int main(){ConMediator mediator;People p1(&mediator, "people1");People p2(&mediator, "people2");People p3(&mediator, "people3");mediator.registerPeople(&p1);mediator.registerPeople(&p2);mediator.registerPeople(&p3);p1.sendMsg("people1 send");//一发多收,中介者是中间处理层 return 0;
}

运行:
在这里插入图片描述

6.备忘录模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象外保存这个状态。
代码:

//游戏过程中保存游戏状态,快照 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;//备忘录类 
class GameState{private:vector<string> histories;public:GameState(){}GameState(GameState* other){histories = other->getHistory();}void addHistory(string& history){histories.push_back(history);}string getState(){return histories[histories.size()-1];}vector<string>& getHistory(){return histories;}
}; //测试游戏类
class Game{private:GameState* state;public:Game(){state = new GameState;}Game(GameState* state) : state(state){}~Game(){delete state;}GameState* getState(){return state;}//游戏具体操作方法void operation(string opera){cout << "game operation : " << opera << endl;state->addHistory(opera);}string getCurrentState(){return state->getState();}
}; int main(){Game game;game.operation("move left");game.operation("fire");game.operation("stop");GameState state(game.getState());//另一个对象保存当前游戏状态 Game newGame(&state);//新建游戏,继承之前的游戏状态 string cState = newGame.getCurrentState();cout << "new game state : " << cState << endl;return 0;
}

运行:
在这里插入图片描述

7.观察者模式

定义对象间的一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都被通知到并被自动更新。
代码:

//一个更改,全部通知 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;class ObserverBase;//抽象目标
class TargetBase{public:virtual void notify() = 0;virtual void attach(ObserverBase* ob) = 0;		
}; //抽象观察者
class ObserverBase{public:ObserverBase(TargetBase* tar){tar->attach(this);} virtual void update() = 0; 
}; //具体目标
class  Target : public TargetBase{private:int val;vector<ObserverBase*> observers;public:void set(int val){this->val = val;notify();}int get(){return val;}void notify() override{//群发通知cout << "notify" << endl;for(ObserverBase* ob : observers){ob->update();} }void attach(ObserverBase* ob) override{observers.push_back(ob);}
};//具体观察者
class Observer : public ObserverBase{private:Target* target;string name;public:Observer(Target* target,string name) : ObserverBase(target),target(target),name(name){}void update() override{cout << name << "->target val changed : " << target->get() << endl;}
};int main(){	Target t1;Observer observer1(&t1,"observer1");Observer observer2(&t1,"observer2");//两个订阅观察者 t1.set(1);//一次设置,两个接收 return 0;
}

运行:
在这里插入图片描述

8.状态模式

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
代码:

#include <iostream>
#include <string.h>
#include <vector>
using namespace std;//抽象状态类
class StateBase{public:virtual void handle() = 0;
}; //多种状态
class State1 : public  StateBase{void handle(){cout << "state 1 out" << endl;}
};
class State2 : public  StateBase{void handle(){cout << "state 2 out" << endl;}
};//操作目标
class Target{private:StateBase* state;public:void setState(StateBase* state){this->state = state;}void apply(){state->handle();}
}; int main(){Target target;State1 state1;target.setState(&state1);//更新target的状态 target.apply();State2 state2;target.setState(&state2);//更新target的状态target.apply();//同样的行为,通过改变外部state2状态,产生不同的效果 return 0;
}

运行:
在这里插入图片描述

9.策略模式

定义一系列算法,并把它们一个个封装起来,并且使得它们可以互相替换。
代码:

//将不同的策略封装起来,不同情况下不同策略 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;//一个策略基类
class Strategy{public:virtual void handle() = 0;//排序完,输出最大值 
}; 
//具体策略
class Strategy1 : public Strategy{void handle() override{cout << "Strategy1 handle" << endl;}
};
class Strategy2 : public Strategy{void handle() override{cout << "Strategy2 handle" << endl;}
};//集体操作类,联系上下文场景确定策略 
class  Context{private:Strategy* strategy;public:void setScene(Strategy* sgy){//配置场景 strategy = sgy;}void execute(){//确定具体策略 strategy->handle();}
};int main(){Context con;//场景1Strategy1 s1;con.setScene(&s1);con.execute();//场景2Strategy2 s2;con.setScene(&s2);con.execute(); return 0;
}

运行:
在这里插入图片描述

10.模板方法模式

定义一个操作中的算法骨架,而将一些步骤延迟到子类,使得子类可以不改变一个算法结构即可重定义该算法的某些特定步骤。
代码:

//典型是C++模板操作,这里用其他例子,比如建房子 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;//抽象基类,定义一套框架
class  Build{public: void buildAll(){//定义一台公用框架 buildGround();buildFramework();buildDecoration(); }protected:virtual void buildGround() = 0;//打地基virtual void buildFramework() = 0;//做框架virtual void buildDecoration() = 0;//装修
};//具体实现,实现具体方法
class BuildHighHouse : public Build{protected:void buildGround() override{cout << "deep" << endl;}void buildFramework() override{cout << "wide" << endl;}void buildDecoration() override{cout << "luxurious" << endl;}
};
class BuildLowHouse : public Build{protected:void buildGround() override{cout << "shallow" << endl;}void buildFramework() override{cout << "thin" << endl;}void buildDecoration() override{cout << "simple" << endl;}
};int main(){//cout << "build high house*******" << endl; BuildHighHouse h;h.buildAll();cout << "build low house*******" << endl; BuildLowHouse l;l.buildAll();return 0;
} 

运行:
在这里插入图片描述

11.访问者模式

封装一些作用于某种数据结构中各元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的操作。主要为了实现数据结构与数据操作的分离。
代码:

//访问电脑不同元件 
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;class Mouse;
class Keyboard;
//抽象访问者,操作方法的集合体 
class  VisitorBase{public:virtual void visit(Mouse* mouce) = 0;virtual void visit(Keyboard* keyboard) = 0;
}; //抽象访问元素 
class Computer{public:virtual void accept(VisitorBase* v) = 0;
};
//具体几个访问元素
class Mouse : public Computer{public:void accept(VisitorBase* v) override{v->visit(this);}
}; 
class Keyboard : public Computer{public:void accept(VisitorBase* v) override{v->visit(this);}
}; //访问者具体实现 
class Visitor : public VisitorBase{void visit(Mouse* mouse) override{cout << "this is mouse" << endl;}void visit(Keyboard* keyboard) override{cout << "this is keyboard" << endl;}
};int main(){Visitor v;Mouse m;m.accept(&v);//通过元素类型,定位到元素的具体操作方法;Mouse算数据结构,Visit算数据结构的操作方法 Keyboard k;k.accept(&v);return 0;
}

运行:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477845.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

渗透测试---shell(7)for循环2与while循环

声明&#xff1a;学习素材来自b站up【泷羽Sec】&#xff0c;侵删&#xff0c;若阅读过程中有相关方面的不足&#xff0c;还请指正&#xff0c;本文只做相关技术分享,切莫从事违法等相关行为&#xff0c;本人与泷羽sec团队一律不承担一切后果 视频地址&#xff1a;泷羽--shell&a…

CLIP-Adapter: Better Vision-Language Models with Feature Adapters 论文解读

abstract 大规模对比视觉-语言预训练在视觉表示学习方面取得了显著进展。与传统的通过固定一组离散标签训练的视觉系统不同&#xff0c;(Radford et al., 2021) 引入了一种新范式&#xff0c;该范式在开放词汇环境中直接学习将图像与原始文本对齐。在下游任务中&#xff0c;通…

C++初阶(十五)--STL--list 的深度解析与全面应用

文章目录 一、头文件与基本概念 二、构造函数和析构函数 1.构造函数 2.析构函数 三、元素访问 front back 四、迭代器相关函数 begin end rebegin&#xff08;反向迭代器&#xff09; rend&#xff08;反向迭代器&#xff09; 五、容量相关函数 empty size max…

一个关于 CSS Modules 的陷阱

我在引用 less 文件样式的时候&#xff0c;发现 index.less .drag_upload {width: 100%;height: 90vh;padding: 20px; }index.jsx import React, { useState, useEffect } from react; import styles from ./index.less;export default ({ }) > {return (<div classNa…

基于STM32的智能家居电器控制系统

目录 引言环境准备 2.1 硬件准备 2.2 软件准备智能家居电器控制系统基础 3.1 控制系统架构 3.2 功能描述代码实现&#xff1a;实现智能家居电器控制系统 4.1 数据采集模块 4.2 控制逻辑与设备管理 4.3 通信与远程控制实现 4.4 用户界面与数据可视化应用场景&#xff1a;家庭自…

视觉经典神经网络与复现:深入解析与实践指南

目录 引言 经典视觉神经网络模型详解 1. LeNet-5&#xff1a;卷积神经网络的先驱 LeNet-5的关键特点&#xff1a; 2. AlexNet&#xff1a;深度学习的突破 AlexNet的关键特点&#xff1a; 3. VGGNet&#xff1a;深度与简洁的平衡 VGGNet的关键特点&#xff1a; 4. ResNe…

vue3【实战】响应式的登录界面

效果预览 WEB 端效果 移动端效果 技术方案 vue3 vite Element Plus VueRouter UnoCSS TS vueUse AutoImport 技术要点 响应式设计 移动端&#xff1a;图片切换为绝对定位&#xff0c;下移一层&#xff0c;成为背景图片 <el-imageclass"w-screen h-screen lt-md…

c语言的qsort函数理解与使用

介绍&#xff1a;qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活&#xff0c;可以对任意类型的元素进行排序&#xff0c;只要提供了比较函数即可。 qsort 函数原型及参数解释&#xff1a; void qsort ( void* base, //指向要排序的数组的首元素…

AIGC学习笔记(6)——AI大模型开发工程师

文章目录 AI大模型开发工程师005 OpenAI大模型案例实践1 AI 翻译助手需求分析项目起源市场价格和市场前景基于大模型的翻译软件核心功能设计 2 AI 翻译助手架构设计架构设计代码结构设计 3 AI 翻译助手核心功能文档解析文档操作PDF文档操作表格操作图片操作 Prompt封装 4 AI 翻…

《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part1

资料来自李宏毅老师《生成式 AI》课程&#xff0c;如有侵权请通知下线 Introduction to Generative AI 2024 Spring 该文档主要介绍了国立台湾大学&#xff08;NTU&#xff09;2024 年春季 “生成式人工智能&#xff08;GenAI&#xff09;” 课程的作业 5&#xff08;GenAI HW…

cangjie (仓颉) vscode环境搭建

sdk下载 下载中心-仓颉编程语言官网 可选择半年更新版&#xff0c;不用申请。目前版本&#xff1a;0.53.13 &#xff0c;选择不同平台压缩包下载解压到任意位置即可 补充下载&#xff0c;vscode插件解压后&#xff0c;在vscode扩展中选择从vsix安装&#xff0c;安装后新增名为…

微信小程序全局配置:导航栏、下拉刷新与上拉触底设置教程

微信小程序全局配置:导航栏、下拉刷新与上拉触底设置教程 引言 微信小程序作为一种新兴的轻量级应用,凭借其便捷性和丰富的功能受到了广泛的欢迎。在开发小程序的过程中,合理配置全局属性是提升用户体验的关键。本文将深入探讨小程序的全局配置中的window选项,重点介绍导…

CPU命名那些事

一、Intel CPU命名 1. 命名结构 Intel CPU 的命名通常包含以下几个部分&#xff1a; 品牌 产品线 系列 代数 具体型号 后缀 例如&#xff1a;Intel Core i7-13700K 2. 各部分含义 品牌 Intel&#xff1a;表示厂商&#xff08;几乎所有命名中都有&#xff09;。不同品…

【C++笔记】数据结构进阶之二叉搜索树(BSTree)

【C笔记】数据结构进阶之二叉搜索树(BSTree) &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】数据结构进阶之二叉搜索树(BSTree)前言一.二叉搜索树的概念二.二叉搜索树的性能分析三.二叉搜索树的实现3.1二叉树的中序…

无线图传下的低延迟视频传输播放技术探讨

技术背景 无线图传技术即无线图像传输技术&#xff0c;是指不用布线&#xff08;线缆&#xff09;利用无线电波来传输图像数据的技术。 一、工作原理 无线图传技术主要涉及图像采集、编码、调制、发射、接收、解调、解码和图像显示等环节。 图像采集&#xff1a;通过摄像头…

Linux的开发工具(三)

条件编译 预处理本质&#xff1a;对代码进行裁剪 像网易云音乐有vip和普通用户&#xff0c;可以通过条件编译来&#xff0c;这样只用写一份代码&#xff0c;也只用维护一份代码&#xff0c;是vip就走vip代码&#xff0c;不是就普通用户代码&#xff0c;条件编译来动态裁剪。 …

VSCode 汉化教程【简洁易懂】

VSCode【下载】【安装】【汉化】【配置C环境&#xff08;超快&#xff09;】&#xff08;Windows环境&#xff09;-CSDN博客 我们安装完成后默认是英文界面。 找到插件选项卡&#xff0c;搜索“Chinese”&#xff0c;找到简体&#xff08;更具你的需要&#xff09;&#xff08;…

Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成

Ubuntu下的DoxygenVScode实现C/C接口文档自动生成 1、 Doxygen简介 Doxygen 是一个由 C 编写的、开源的、跨平台的文档生成系统。最初主要用于生成 C 库的 API 文档&#xff0c;但目前又添加了对 C、C#、Java、Python、Fortran、PHP 等语言的支持。其从源代码中提取注释&…

Linux网络——网络层

网络层的作用&#xff1a;在复杂的网络环境中确定一个合适的路径。 一.IP协议 IP存在的意义&#xff1a;IP地址提供一种能力&#xff0c;使得数据能够从主机B跨网络、可靠的送至主机A。 1.协议头格式 能够看出IP协议的格式与TCP协议存在很多相似之处&#xff0c;同样拥有4为首…

Shiro-550反序列化漏洞分析

&#x1f338; 环境配置 代码下载地址&#xff1a;https://codeload.github.com/apache/shiro/zip/refs/tags/shiro-root-1.2.4 下载完成之后&#xff0c;需要修改一下pom文件&#xff1a; 修改一下红色框中的配置。然后配置一下tomcat&#xff1a; 点击部署&#xff0c;然后…