原型模式

这个模式也比较常见,但是可能不常用。解决的也是对象创建的问题,但是这个和工厂模式有点不同,工厂模式可能创建的是一个新的对象,
但是这个对象的具体的状态可能你不太关心,可能一个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.
posted @ 2020-11-22 19:27  cyssmile  阅读(97)  评论(0编辑  收藏  举报