工厂模式主要解决,同一类接口,不同厂家有不同实现这类问题。
以业务集成相机sdk为例,相机常用到的功能有打开相机、读取流、关闭流、设置相机参数等。但不同厂家sdk实现方式不一样,如果不用工厂模式,那相同的业务代码,可能要写很多份。使用后,整体代码变得简洁,耦合性好。下面举例说明。
1.抽象相机基类
基类中通常包含两类接口,一类是通用接口,这类接口和相机厂家无关,但相机创建时候又都会用到。另一类是纯虚函数接口,这类接口就是相机相关操作的抽象,如打开相机等。
基类头文件
cpp
#ifndef _ICAMERA_H_
#define _ICAMERA_H_
#include <string>
#include <map>
class ICamera
{
public:
ICamera(std::string cameraName) :name(cameraName) {};
/**
* @brief 加载本地图片,仿真使用
* @param cameraName
* @param simPicDir
*/
ICamera(std::string cameraName, std::string picDir);
virtual ~ICamera() = default;
/*************************相机厂家重写*************************/
/**
* @brief 相机初始化
* @return
*/
virtual void init(CameraManagePara cmPara) = 0;
/**
* @brief 设置相机参数
* @param para
* @return
*/
virtual bool setParameter(CameraThreadPara para) = 0;
/**
* @brief 相机在线状态
* @return
*/
virtual bool isOnline() = 0;
/**
* @brief 句柄是否有效
* @return
*/
virtual bool isValidHandle() = 0;
/**
* @brief 关闭相机
*/
virtual void close() = 0;
/**
* @brief 关闭流
* @param
*/
virtual void stopGrab() = 0;
/*************************基类通用接口-厂家不需要实现*************************/
/**
* @brief 获取相机名称
* @return
*/
std::string getCameraName();
/**
* @brief 可以抽取出来的通用逻辑
* @return
*/
void commonFun(std::string picDir);
public:
/**
* @brief 通用成员变量
*/
uint64_t frameTime = 0;
uint64_t frameId = 0;
/**
* @brief 相机名称
*/
std::string name;
};
#endif // !_ICAMERA_H_
基类源文件
cpp
#include "ICamera.h"
ICamera::ICamera(std::string cameraName, std::string picDir)
{
name = cameraName;
commonFun(picDir);
}
std::string ICamera::getCameraName()
{
return name;
}
void ICamera::commonFun(std::string picDir)
{
//业务逻辑
}
2.具体相机子类
这里只举例一个厂家,如果多个厂家,写多个子类就行。
头文件
cpp
#ifndef _DSCAMERA_H_
#define _DSCAMERA_H_
#include "ICamera.h"
#include "DVPCamera.h"
class DSCamera : public ICamera
{
public:
~DSCamera() override { close(); }
DSCamera(std::string cameraName, std::string simPicDir)
: ICamera(cameraName, simPicDir) {}
/**
* @brief 相机初始化
* @return
*/
virtual void init(CameraManagePara cmPara) override;
/**
* @brief 设置相机参数
* @param para
* @return
*/
virtual bool setParameter(CameraThreadPara para) override;
/**
* @brief 相机在线状态
* @return
*/
virtual bool isOnline() override;
/**
* @brief 句柄是否有效
* @return
*/
virtual bool isValidHandle() override;
/**
* @brief 关闭相机
*/
virtual void close() override;
/**
* @brief 关闭流
* @param
*/
virtual void stopGrab() override;
private:
//bool isValidHandle();
void connect(CameraManagePara cmPara);
//相机原生句柄
dvpHandle handle;
};
#endif // !_DSCAMERA_H_
源文件
cpp
#include "DSCamera.h"
dvpInt32 dSCameraCallBack(dvpHandle handle, dvpStreamEvent event, void* pContext, dvpFrame* pFrame, void* pBuffer)
{
DSCamera* pThis = (DSCamera*)pContext;
//基类通用变量
pThis->frameId = pFrame->uFrameID;
//回调取图
cv::Mat mat = cv::Mat(pFrame->iHeight, pFrame->iWidth, CV_8UC3, (uchar*)pBuffer, pFrame->iWidth * 3).clone();
return 0;
}
void DSCamera::init(CameraManagePara cmPara)
{
connect(cmPara);
}
bool DSCamera::setParameter(CameraThreadPara para)
{
dvpStatus status;
//关闭流
status = dvpStop(handle);
//设置相机参数等等
//开启流
status = dvpStart(handle);
return true;
}
bool DSCamera::isOnline()
{
if (!isValidHandle())
return false;
dvpStatus status;
bool online = false;
status = dvpIsOnline(handle, &online);
if (status != DVP_STATUS_OK)
{
LOG(ERROR) << " get online status error " << std::endl;
return false;
}
return online;
}
void DSCamera::close()
{
//关闭视频流
dvpStatus status = dvpStop(handle);
//关闭相机
dvpStatus status1 = dvpClose(handle);
}
bool DSCamera::isValidHandle()
{
bool isValid = false;
dvpStatus status = dvpIsValid(handle, &isValid);
if (status != DVP_STATUS_OK) {
return false;
}
return isValid;
}
void DSCamera::stopGrab()
{
dvpStatus status = dvpStop(handle);
}
void DSCamera::connect(CameraManagePara cmPara)
{
dvpStatus status;
status = dvpOpenByUserId(name.c_str(), OPEN_NORMAL, &handle);
//设置相机属性-略
//设置回调
status = dvpRegisterStreamCallback(handle, dSCameraCallBack, STREAM_EVENT_FRAME_THREAD, this);
}
3.抽象工厂
通过工厂来创建具体子类对象。
cpp
#ifndef _ICAMERAFACTORY_H_
#define _ICAMERAFACTORY_H_
#include "ICamera.h"
#include "DSCamera.h"
#include "DHCamera.h"
#include "MDWSCamera.h"
class ICameraFactory
{
public:
virtual ~ICameraFactory() = default;
// 创建对应厂商相机实例
virtual ICamera* createCamera(std::string cameraName, std::string picPath) = 0;
};
class DSCameraFactory : public ICameraFactory
{
public:
ICamera* createCamera(std::string cameraName, std::string picPath) override
{
return new DSCamera(cameraName, picPath);
}
};
class DHCameraFactory : public ICameraFactory
{
public:
ICamera* createCamera(std::string cameraName, std::string picPath) override
{
return new DHCamera(cameraName, picPath);
}
};
class MDWSCameraFactory : public ICameraFactory
{
public:
ICamera* createCamera(std::string cameraName, std::string picPath) override
{
return new MDWSCamera(cameraName, picPath);
}
};
class CameraFactoryManager
{
public:
// 根据相机类型创建相机实例
static ICamera* createCamera(const std::string& camType, const std::string& camName, const std::string& picPath)
{
if (camType == "DS") {
return DSCameraFactory{}.createCamera(camName, picPath);
}
else if (camType == "DH")
{
return DHCameraFactory{}.createCamera(camName, picPath);
}
else if (camType == "MDWS")
{
MDWSCameraFactory factory;
return MDWSCameraFactory{}.createCamera(camName, picPath);
}
else
{
throw std::runtime_error("unsupported camera type: " + camType);
}
}
};
#endif // !_ICAMERAFACTORY_H_