vendredi 7 octobre 2022

What does this static member data do in the implementation of protype design pattern in book "Design Patterns explained simply"

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