Prototype设计模式理解
对于设计模式每一次听完看完都有一种让人觉得十分优雅得感觉
以下是我对这个设计模式得理解(新手理解,还望指正):
首先,由于我们无法预测未来我们所设计得父类在后面会衍生出什么子类,难以去确定子类的名称,但是我们又需要在我们的父类中使用到未来的子类,所以采用此设计模式。下面以代码作为解读.
代码解读
代码片
.注:以下代码来自侯捷老师课程
#include <iostream>
using namespace std;
enum imageType
{
LSAT, SPOT
};
class Image
{
public:
virtual void draw() = 0;
static Image* findAndClone(imageType);
protected:
//两个纯虚函数,让未来的子类能够自己定义实现自己的特征
virtual imageType returnType() = 0;
virtual Image* clone() = 0;
// As each subclass of Image is declared, it registers its prototype
static void addPrototype(Image* image)
{
_prototypes[_nextSlot++] = image;
}
private:
// addPrototype() saves each registered prototype here
static Image* _prototypes[10];
static int _nextSlot;
};
//设计的静态变量或者对象要在类外分配内存
Image* Image::_prototypes[];
int Image::_nextSlot;
// Client calls this public static member function when it needs an instance
// of an Image subclass
//这里我认为写的很美,这个就是父类能够去注册子类的关键
Image* Image::findAndClone(imageType type)
{
for (int i = 0; i < _nextSlot; i++)
if (_prototypes[i]->returnType() == type)
return _prototypes[i]->clone();
}
class LandSatImage : public Image
{
public:
imageType returnType() {
return LSAT;
}
void draw() {
cout << "LandSatImage::draw " << _id << endl;
}
// When clone() is called, call the one-argument ctor with a dummy arg
Image* clone() {
return new LandSatImage(1);
}
protected:
// This is only called from clone()
LandSatImage(int dummy) {
_id = _count++;
}
private:
// Mechanism for initializing an Image subclass - this causes the
// default ctor to be called, which registers the subclass's prototype
//这里的静态设置,会默认的调用下面的构造函数,创建一个初始的子类
static LandSatImage _landSatImage;
// This is only called when the private static data member is inited
LandSatImage() {
addPrototype(this);
}
// Nominal "state" per instance mechanism
int _id;
static int _count;
};
// Register the subclass's prototype
//由于我们设置的static,所以要在外部声明,那么就会调用默认的构造函数
//默认构造函数会调用addPrototype(this);把自己添加在父类的_prototypes[_nextSlot++] = image;这里也就相当于刚刚开始就会有_prototypes[0]就是LandSatImage 。
LandSatImage LandSatImage::_landSatImage;
// Initialize the "state" per instance mechanism
int LandSatImage::_count = 1;
int main() {
// 假设我们需要一个LandSatImage类型的图像
Image* image = Image::findAndClone(LSAT);
// 使用这个图像实例来绘制图像
image->draw();
// 当我们完成图像处理后,释放内存
delete image;
return 0;
}
这里面最主要的应该是就类中的静态变量要在外部进行内存的分配,这里我理解了好久,LandSatImage LandSatImage::_landSatImage;这句话十分需要去理解,在类外部使用这句话,也就是刚刚开始的时候Image的_prototypes[0]就是LandSatImage。
原因如下:
在C++中,静态成员变量在程序启动时就会被初始化,即使它们所在的类还没有被显式地使用。因此,LandSatImage::_landSatImage 作为一个静态成员,在程序开始运行时就被初始化了,其构造函数中的 addPrototype(this) 调用确保了 LandSatImage 的原型被添加到了 _prototypes 数组中。
所以,当你执行 Image* image = Image::findAndClone(LSAT); 时,_prototypes 数组已经包含了 LandSatImage 的原型,findAndClone 函数会找到这个原型并调用它的 clone 方法来创建一个新的 LandSatImage 实例。这就是为什么在你调用 findAndClone 方法之前,_prototypes[0] 已经是 LandSatImage 的原因。这个机制允许程序在需要时快速地创建特定类型的 Image 实例,而不需要知道具体的子类信息