I'm implementing a simple data reader to get image sequences from either a pre-recorded video file, or a camera device. Basically I intend for users to use it in the following way:
When a non-empty file path is provided, the reader reads from the video file; otherwise if an empty path is specified, the reader reads from the camera device. (For now in case of any failure, throwing exceptions and terminating the program will be fine.)
The user iteratively calls bool get_next_frame(Frame&)
to get all the frames, until reaching the end of the video, upon which the function returns false
.
I'm trying to implement the above-mentioned functionality using the factory pattern, in C++ as follows:
class DataReader;
typedef std::shared_ptr<DataReader> datareader_ptr;
// base class
class DataReader {
friend datareader_ptr make_data_reader(const std::string& file_path);
public:
virtual bool get_next_frame(Frame& frame)=0;
virtual ~DataReader() {}
protected:
// “pipeline” is concerned with some libraries I use to read from file or camera
DataReader(pipeline pipe);
pipeline pipe_;
};
// Derived class 1, reading from file
class FileDataReader : public DataReader {
friend datareader_ptr make_data_reader(const std::string& file_path);
public:
virtual bool get_next_frame(Frame& frame) {
// code for reading a frame from file
}
virtual ~FileDataReader() {}
protected:
FileDataReader(pipeline pipe):DataReader(pipe){};
};
// Derived class 2, reading from camera
class CameraDataReader : public DataReader {
friend datareader_ptr make_data_reader(const std::string& rfile_path);
public:
virtual bool get_next_frame(Frame& frame) {
// reading frame from camera
}
virtual ~CameraDataReader() {}
protected:
CameraDataReader(pipeline pipe):DataReader(pipe) {}
};
// The factory function that creates the reader.
// The user is only allowed to use this function to create the reader instances.
datareader_ptr make_data_reader(const std::string& file_path) {
pipeline pipe;
if (file_path=="") {
// set up pipe to read from camera
return datareader_ptr(new CameraDataReader(pipe));
} else {
// set up pipe to read from file
return datareader_ptr(new FileDataReader(pipe));
}
}
However, I'm really not sure whether this is the best practice. More specifically,
- Is the usage of factory pattern here justified ?
- Is my implementation of factory pattern correct ? Or are there any pitfalls in the code ?
For example, I used friend function to access the protected constructors in all the classes, is this appropriate or there are better ways to do this?
Another example, protected constructor is used so that the users may not directly construct the readers, but only through the factory function. Is this done correctly?
Thanks in advance!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…