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

news2024/11/25 12:20:10

前边搞定了驱动,先不着急直接上手撸应用层的代码,先了解一下大致要用到的东西。
设计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;
			else
				cout << "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());//代理访问 Subject1
	proxy->request();
	
	unique_ptr<Proxy> proxy2 = make_unique<Proxy>(sub2.get());//代理访问 Subject2
	proxy2->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->high
	
	Request 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;//给中介介绍people
		virtual 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;
	//场景1
	Strategy1 s1;
	con.setScene(&s1);
	con.execute();
	
	//场景2
	Strategy2 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.coloradmin.cn/o/2247285.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据新视界 -- Hive 数据分区:精细化管理的艺术与实践(上)(7/ 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

strlwr(arr);的模拟实现(c基础)

hi , I am 36 适合对象c语言初学者 strlwr(arr)&#xff1b;函数是把arr数组变为小写字母,并返回arr 链接介绍一下strlwr(arr)&#xff1b;(c基础)-CSDN博客 下面进行My__strlwr(arr);模拟实现 #include<stdio.h> //返回值为arr(地址),于是用指针变量,原数组为字符型…

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想&#xff0c;将代码与数据分离&#xff0c;易维护&#xff0c;易上手。使用yaml编写编写测试用例&#xff0c;利用requests库发送请求&#xff0c;使用pytest管理用例&#xff0c;allure生成…

Sigrity SPEED2000 General SI Simulation模式如何进行信号仿真分析操作指导-DDR

Sigrity SPEED2000 General SI Simulation模式如何进行信号仿真分析操作指导-DDR Sigrity SPEED2000 General SI Simulation模式可以对信号进行仿真分析,仿真将电源视为理想电源,以下图为例进行说明 附带驱动和接收端的IBIS模型 2D 视图

python中如何使用指数

exp()方法&#xff1a; exp(x)方法返回x的指数&#xff0c;e^x。 如x1&#xff0c;那么e的1次幂为2.7183… 语法&#xff1a; 注意&#xff1a;exp()是不能直接访问的&#xff0c;需要导入math模块&#xff0c;通过静态对象调用该方法。 实例&#xff1a; 运行结果&#xf…

AutoDL安装docker问题

在AutoDL上租了卡&#xff0c;安装docker遇到一些问题&#xff1a; 1.执行 sudo docker run hello-world 报错 docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 解决方法 先查看docker有没有启动&#xff0c;…

基于SSM的婚庆管理系统+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、商家&#xff08;婚庆公司&#xff09;、用户功能模块&#xff1a;管理员&#xff08;用户管理、商家管理、摄影风格管理、礼服款式管理、案例管理、婚车品牌管理、婚纱拍摄管理、策划服务管理、婚宴酒店管理、婚车套餐管理、在线咨询…

Linux入门系列--文件与目录

一、介绍 在Linux中&#xff0c;有着一句话&#xff0c;叫做&#xff1a;一切皆文件。也就是任何东西都是以文件的形式存储的。 目录结构 bin&#xff1a;全程binary&#xff0c;含义是二进制。该目录中存储的都是一些二进制文件。我们学过C/C&#xff0c;其实也都知道机器能…

Linux离线安装Docker命令,简单镜像操作

解压安装包 首先&#xff0c;使用 tar 命令解压 docker-27.3.1.tgz 安装包&#xff1a; tar -zxvf docker-27.3.1.tgz 将二进制文件移动到可执行路径上的目录 接着&#xff0c;将解压出来的 Docker 二进制文件复制到系统的可执行路径&#xff08;通常是 /usr/bin/&#xff09…

鸿蒙主流路由详解

鸿蒙主流路由详解 Navigation Navigation更适合于一次开发,多端部署,也是官方主流推荐的一种路由控制方式,但是,使用起来入侵耦合度高,所以,一般会使用HMRouter,这也是官方主流推荐的路由 Navigation官网地址 个人源码地址 路由跳转 第一步-定义路由栈 Provide(PageInfo) pag…

harbor和docker配置https访问

如果配置了科学上网代理&#xff0c;一定要做免代理的配置&#xff0c;不然https访问会失败。 免代理配置 Docker免代理配置 [rootnode1 harbor]#cat /etc/systemd/system/docker.service.d/http-proxy.conf [Service] Environment"HTTP_PROXYhttp://10.0.0.1:7897"…

SageMaker强化学习部署

强化训练 强化学习的训练与一般的深度学习不太一样。需要有一个环境&#xff0c;对智能体的动作&#xff0c;给予一个奖励并进行状态转移。用于训练的数据&#xff0c;是在训练的过程中产生的。 这里以一个小车上坡的强化学习作为例子&#xff0c;相关文档在下方 https://sa…

MySQL面试-1

InnoDB中ACID的实现 先说一下原子性是怎么实现的。 事务要么失败&#xff0c;要么成功&#xff0c;不能做一半。聪明的InnoDB&#xff0c;在干活儿之前&#xff0c;先将要做的事情记录到一个叫undo log的日志文件中&#xff0c;如果失败了或者主动rollback&#xff0c;就可以通…

使用树莓派安装shairport-sync使老音响变身AirPlay音响

借助shairport-sync&#xff0c;可以让普通音响变成AirPlay无线音响&#xff0c;由于树莓派天生的低功耗&#xff0c;做这种事情最适合。所以架构就是树莓派安装Ubuntu24.04&#xff0c;在树莓派上安装shairport-sync&#xff0c;树莓派再通过3.5mm线连接音响。 安装Ubuntu24.…

Linux---ps命令

​​​​​​Linux ps 命令 | 菜鸟教程 (runoob.com) process status 用于显示进程的状态 USER: 用户名&#xff0c;运行此进程的用户名。PID: 进程ID&#xff08;Process ID&#xff09;&#xff0c;每个进程的唯一标识号%CPU: 进程当前使用的CPU百分比%MEM: 进程当前使用的…

VLAN是什么,一个好的网络为什么要划分VLAN呢?

前言 在上一篇中讲解了交换机的工作原理&#xff0c;知道了交换机处理数据的转发方式&#xff0c;其中有两种情况会以广播方式进行发送数据&#xff0c;第一种是目的MAC是全F的&#xff0c;以及组播MAC&#xff0c;第二种是未知单播帧&#xff0c;那这个会带来什么样的问题呢&…

衡山派D133EBS 开发环境安装及SDK编译烧写镜像烧录

1.创建新文件夹&#xff0c;用来存放SDK包&#xff08;其实本质就是路径要对就ok了&#xff09;&#xff0c;右键鼠标通过Open Git Bash here来打开git 输入命令 git clone --depth1 https://gitee.com/lcsc/luban-lite.git 来拉取&#xff0c;如下所示&#xff1a;&#xff0…

基于Gradle搭建Spring6.2.x版本源码阅读环境

前言 阅读源码是程序猿成长的必经一环&#xff0c;正所谓知其然知其所以然。我们在开发成长道路上不仅需要知道如何使用&#xff0c;更要懂得其背后的原理&#xff0c;如此方可得心应手。本篇文章旨在指导大家搭建Spring6.0以上版本的源码阅读环境&#xff0c;方便大家在学习源…

C++自动化测试:GTest 与 GitLab CI/CD 的完美融合

在现代软件开发中&#xff0c;自动化测试是保证代码质量和稳定性的关键手段。对于C项目而言&#xff0c;自动化测试尤为重要&#xff0c;它能有效捕捉代码中的潜在缺陷&#xff0c;提高代码的可维护性和可靠性。本文将重点介绍如何在C项目中结合使用Google Test&#xff08;GTe…

ubuntu16.04在ros使用USB摄像头-解决could not open /dev/video0问题

首先检查摄像头 lsusb 安装 uvc camera 功能包 sudo apt-get install ros-indigo-uvc-camera 安装 image 相关功能包 sudo apt-get install ros-kinetic-image-* sudo apt-get install ros-kinetic-rqt-image-view运行 uvc_camera 节点 首先输入roscore 然后另外开一个终端输入…