原型模式
这个模式也比较常见,但是可能不常用。解决的也是对象创建的问题,但是这个和工厂模式有点不同,工厂模式可能创建的是一个新的对象,
但是这个对象的具体的状态可能你不太关心,可能一个memset就OK了。但是有的时候状态的设置可能是比较复杂的,而且不想写那个过程,那么就可以用原型模式。
常见的原型模式,cv中Mat::clone()方法。
需要关心的有要些好复制构造函数。
比如我有这样一个结构体,用来保存一张图片的数据。
enum class Buffer {
int width;
int height;
int[3] stride;
void* data[3];
};
现在我每次使用的时候,我不想每次都去创建一个这样的Buffer,我想使用之前是用的Buffer应该怎么做呢?
比较常见的做法写复制构造函数或者重写“=”,但是这样的代码一般都不够优美。那么我们就可以写成原型模式。
比如这样一个例子
class Buffer {
private:
unsigned char* data_ = nullptr;
int size_ = 0;
public:
Buffer(int size) : size_(size_) {
data_ = new unsigned char[size_];
}
~Buffer() {
delete[] data_;
data_ = nullptr;
}
};
现在先加上复制构造函数
Buffer::Buffer(const Buffer& src) {
this->size_ = src.size_;
this->data_ = new unsigned char[this->size_];
memcpy(this->data_, src.data_, this->size_);
}
现在写成原型模式,首先想想我们要什么样子的.可能就这个样 Buffer* dst = src->Clone()
那么我们就开始写代码吧
Buffer* Buffer::Clone() {
return new Buffer(*this);
}
没错就是将this解引用作为复制构造函数的参数。
还有就是为了使得Buffer可以在后面扩展,要把析构函数加上virtual关键字
构造函数加上等等,你懂的。
最后就写成这样了
prototype.h
#ifndef __PROTOTYPE_HPP
class Buffer {
//private:
public:
unsigned char* data_ = nullptr;
int size_ = 0;
public:
Buffer(int size);
Buffer(const Buffer& src);
Buffer* Clone();
virtual ~Buffer();
};
#endif // !__PROTOTYPE_HPP
prototype.cpp
#include<cstring>
#include "prototype.h"
Buffer::Buffer(int size) : size_(size) {
data_ = new unsigned char[size_];
}
Buffer::Buffer(const Buffer& src) {
this->size_ = src.size_;
this->data_ = new unsigned char[this->size_];
memcpy(this->data_, src.data_, this->size_);
}
Buffer* Buffer::Clone() {
return new Buffer(*this);
}
Buffer::~Buffer() {
delete[] this->data_;
this->data_ = nullptr;
this->size_ = 0;
}
main.cpp
#include <iostream>
#include "prototype.h"
int main(int argc, char* argv) {
Buffer src(5);
src.data_[0] = 0;
for (int i = 1; i < src.size_; i++) {
src.data_[i] = src.data_[i - 1] + 1;
}
Buffer* dst = src.Clone();
for (int i = 0; i < dst->size_; i++) {
std::cout << (int)dst->data_[i] << " ";
}
std::cout << std::endl;
delete dst;
dst = nullptr;
return 0;
}
定义
使用原型对象的实例创建对象的种类,然后通过拷贝这些原型来创建新的对象。
为什么要这么做呢?
有时候一个对象的创建,其中包含对象自身的一些状态。我们希望通过已有的对象实例创建新的对象,就可以使用原型模式。
要点
- Prototype模式同样用于隔离类对象的使用者和具体的类型之间的耦合性,它要求具体类型拥有一些稳定的接口,可以参考下cv中的Mat。
- Prototype模式对于“如何创建易变类”采用原型克隆的方法来做,它使得我们可以灵活的动态创建“拥有某些稳定接口的新对象”。 只需要创建一个新的对象(原型),
然后在任何需要的地方使用Clone.