观察者Observer模式的代码实现
本项目中采用观察者模式,主要是为了进行数据的传递,如IDemux解封装出的音视频码流数据时,通知音视频解码类IDecode进行解码
观察者接口类IObserver
#ifndef BOPLAY_IOBSERVER_H
#define BOPLAY_IOBSERVER_H
#include "XData.h"
#include "XThread.h"
#include <vector>
#include <mutex>
//观察者 和 主体
class IObserver : public XThread {
public:
//观察者必须实现, 观察者接受数据函数, 主体调用观察者的update通知观察者已经收到数据了
virtual void update(XData xData){}
//主体函数, 添加观察者(线程安全)
void addObs(IObserver *observer);
//通知所有观察者(线程安全)
void Notify(XData xData);
protected:
//存储所有观察者
std::vector<IObserver *> observers;
//线程锁
std::mutex mux;
};
#endif //BOPLAY_IOBSERVER_H
#include "IObserver.h"
//添加观察者
void IObserver::addObs(IObserver *observer) {
if (!observer){
return;
}
//加锁保证线程安全
mux.lock();
observers.push_back(observer);
mux.unlock();
}
//调用观察者的update方法即通知观察者有新数据
void IObserver::Notify(XData xData) {
mux.lock();
//vector的size()每次调用的时候都会去统计一遍, 如果数量较大, 效率会降低
// for (int i = 0; i < observers.size(); ++i) {
for (auto & observer : observers) {
observer->update(xData);
}
mux.unlock();
}
解封装接口类IDemux使用观察者模式
#ifndef BOPLAY_IDEMUX_H
#define BOPLAY_IDEMUX_H
#include "XData.h"
#include "XThread.h"
#include "IObserver.h"
//解封装接口类继承IOberver实现观察者模式
class IDemux: public IObserver {
public:
//打开文件或者流媒体 rtmp http rtsp
virtual bool Open(const char *url) = 0;
//读取一帧数据,数据由调用者清理
virtual XData Read() = 0;
//总时长(单位ms)
int totalMs = 0;
protected:
//不要让用户访问
virtual void main();
};
#endif //BOPLAY_IDEMUX_H
#include "IDemux.h"
#include "XLog.h"
void IDemux::main() {
while(!isExit){
//解封装线程的主函数主要是读取数据
XData xData = Read();
if (xData.size > 0){
//读取到数据后通知观察者
Notify(xData);
}
}
}