creational pattern: prototype

8
Creational Pattern: Prototype While the Factory Method pattern lets a class defer instantiation to its subclasses, the Prototype pattern uses delegation to accomplish the same task. Chapter 3 – Page 1 Rather than undergo the built-in cost of generating new objects whenever they need to be created, a prototype of the desired object is “cloned” and modified as desired. The prototypes themselves are often created prior to run-time, with their cloned variations added at run- time.

Upload: rob

Post on 22-Feb-2016

52 views

Category:

Documents


0 download

DESCRIPTION

Creational Pattern: Prototype. Chapter 3 – Page 37. While the Factory Method pattern lets a class defer instantiation to its subclasses, the Prototype pattern uses delegation to accomplish the same task. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Creational Pattern: Prototype

Creational Pattern: PrototypeWhile the Factory Method pattern lets a class defer instantiation to its subclasses, the Prototype pattern uses delegation to accomplish the same task.

Chapter 3 – Page 1

Rather than undergo the built-in cost of generating new objects whenever they need to be created, a prototype of the desired object is “cloned” and modified as desired.The prototypes themselves are often created prior to run-time, with their cloned variations added at run-time.

Page 2: Creational Pattern: Prototype

The Prototype PatternThe Prototype declares an interface for cloning itself.

Chapter 3 – Page 2

Each ConcretePrototype implements an operation for cloning itself.The Client creates a new object by asking the Prototype to clone itself.Note that the Prototype pattern is unique among the Creational Design Patterns in that it doesn’t actually require a class; some pure object-oriented languages (e.g., Self, Omega) do away with classes entirely and rely exclusively on prototypes to create new objects.

ConcretePrototype1

Clone()

return a copy of this

ConcretePrototype2

Clone()

return a copy of this

Client

Operation()

Prototype

Clone()

p=Prototype.Clone()

Page 3: Creational Pattern: Prototype

Non-Software ExampleAssume that an e-commerce application gathers product information via complicated queries against a legacy database, which is updated at a known set of predefined intervals.

Chapter 3 – Page 3

BookNumberPagesAuthorPublisher

Clone()

DVDDurationStarStudio

Clone()

ProductCache

GetProduct()LoadCache()

Product

Clone()

The application could instantiate the product information (via cloning) at these predefined intervals and keep it in a cache.

When a user requests information about a certain product, it is retrieved from the cache and cloned.

When the legacy database is updated, the contents of the cache are discarded and reloaded with new objects.

Page 4: Creational Pattern: Prototype

Chapter 3 – Page 4

Whenever the client needs a clone of a particular type, the clone() operator is called on the correct derived class.

Prototype Example: ImagesThe client is using two types of satellite images, the American LandSat images and the European SPOT images, implemented as subclasses of an Image prototype.

LandSatImage

returnType()draw()clone()

SpotImage

returnType()draw()clone()

Client Image

findAndClone()returnType()draw()clone()

Page 5: Creational Pattern: Prototype

C++ Code for Image PrototypeChapter 3 – Page 5

#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(); return NULL;}

Page 6: Creational Pattern: Prototype

Chapter 3 – Page 6

class LandSatImage: public Image { public: imageType returnType() { return LSAT; } void draw() { cout << "LandSatImage::draw " << id << endl; }

// When clone() is called, call the one-argument // constructor 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 // constructor 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;

Page 7: Creational Pattern: Prototype

Chapter 3 – Page 7class 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;

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

void main() { Image *images[NUM_IMAGES]; int i;

// Given an image type, find the right prototype, and return a clone for (i = 0; i < NUM_IMAGES; i++) images[i] = Image::findAndClone(input[i]);

// Demonstrate that correct image objects have been cloned for (i = 0; i < NUM_IMAGES; i++) images[i]->draw();

// Free the dynamic memory for (i = 0; i < NUM_IMAGES; i++) delete images[i]; }

Page 8: Creational Pattern: Prototype

Prototype Design AdvantagesChapter 3 – Page 8

• The Prototype pattern hides the complexities of making new instances from the client, which can be very helpful when there is a complex class hierarchy and new objects of many different types need to be created.

• If the objects are complicated enough, copying an object can be more efficient that creating a new one.

• In addition to the inheritance-vs.-delegation difference, the Prototype pattern differs from the Factory Method pattern in that Prototype doesn’t require subclasses but does require initialization, while Factory Method doesn’t require initialization but does require subclasses.