I am studying this piece of code in the book "Design Patterns explained simply".
It is the implementation of protpe design pattern by the author Alexander Shvets.
Although I thikn I have undrstand most of it, but the static variable _landSatImage
have confued me for several days.
By the comment of the author, it seems to register the subclass.
But how? When, where and how it is used to register the subclasses?
Anyone can give me some clue? Thanks :)
#include <iostream>
#include <vector>
using namespace std;
//--------------------- 1 Image
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:
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();
}
//----------------------- 2 LandSatImage
class LandSatImage: public Image
{
public:
imageType returnType()
{
return LSAT; // return LandSatImage 这样写对吗?
}
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
LandSatImage LandSatImage::_landSatImage;
// Initialize the "state" per instance mechanism
int LandSatImage::_count = 1;
//------------------------------ 3 SpotImage
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;
//----------------------------------------- main
// 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];
}
Aucun commentaire:
Enregistrer un commentaire