C++设计模式 ——prototype pattern

原文参考书籍:《Design Patterns Explained Simply》

一、定义

根据保存的原型寻找需创建对象的类型,再通过拷贝(clone)依据类型创建新的对象。


二、结构



三、要点

  1. 原型模式中,Client并不知道要克隆对象的实际类型,只需知道基类类型即可。
  2. 克隆对象比直接创建对象的优点在于,克隆是将原有对象的行为属性带到了新的对象中。
  3. C++没有克隆方法,要克隆一个对象,需要借助拷贝构造函数(Copy Constructor)来实现。拷贝构造函数中实现拷贝对象有浅拷贝和深拷贝。

四、代码

1. prototype.h

#ifndef PROTOTYPE_H
#define PROTOTYPE_H

#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 yhen 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
LandSatImage LandSatImage::_landSatImage;
// Initialize the"state" per instance mechanism
int LandSatImage::_count = 1;


class SpotImage:public Image
{
public:
	imageType returnType(){
		return SPOT;
	}
	void draw(){
		cout <<"SpotImage:draw"<<_id<<endl;
	}
	Image *clone(){
		return new SpotImage(1);
	}

protected:
	SpotImage(int dummy){
		_id=_count++;
	}
	
private:
	SpotImage(){
		addPrototype(this);
	}
	static SpotImage _spotImage;
	int _id;
	static int _count;
};

SpotImage SpotImage::_spotImage;
int SpotImage::_count = 1;

#endif

2. prototype.cpp

#include "prototype.h"

// Simulated stream of creation requests
const int NUM_IMAGES=8;
imageType input[NUM_IMAGES]=
{
	LSAT,LSAT,LSAT,SPOT,LSAT,SPOT,SPOT,LSAT
};

int main()
{
	Image *images[NUM_IMAGES];
	// Given an image type,find the right prototype,and return a clone
	for(int i=0;i<NUM_IMAGES;i++)
		images[i]=Image::findAndClone(input[i]);
	//Demonstrate that correct image objects have been cloned
	for(int i=0;i<NUM_IMAGES;i++)
		images[i]->draw();
	// Free the dynamic memory
	for(int i=0;i<NUM_IMAGES;i++)
		delete images[i];
	return 0;
}

猜你喜欢

转载自blog.csdn.net/u011254180/article/details/80086190