I am learning about the different design patterns and I have a strong feeling I am missing an essential piece (or pieces) in understanding this particular pattern.
I
You've got the prototype pattern right by the looks of it.
Lets say you're making MineCraft and you're using the prototype pattern for each different kind of block (e.g. dirt, stone, etc). All the prototype objects are actually of the same class Block
, but each object has had different properties set on it so that it looks and behaves differently, for example:
prototypes.dirt = new Block;
prototypes.dirt.texture = new Image("dirt.jpg");
prototypes.dirt.hardness = 1;
prototypes.stone = new Block;
prototypes.stone.texture = new Image("stone.jpg");
prototypes.stone.hardness = 9;
So instead of subclassing where you would write new DirtBlock
or new StoneBlock
, you would instead write prototypes.dirt.clone()
or prototypes.stone.clone()
. No subclassing is required, but you still have the option to subclass if need be.
As for when to choose the prototype pattern instead of a factory pattern, there are two situations I can think of where they differ:
You can iterate over a list of prototypes, but you can't iterate over all the methods on an abstract factory^. Continuing from the code above, you could create a random block like so:
prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();
If you were using the factory method to make blocks, it would be harder to get a random block.
Where creation of an object is expensive, but copying is cheap, the prototype pattern will be more efficient. For example, take this factory method:
Image loadUserImage() {
//loads from disk. will be slow
return new JPEGImage("path/to/user/image.jpg");
}
If this method is going to be called repeatedly, it would be more efficient to use a prototype like so:
Image loadUserImage() {
//copy in memory. will be fast
return userImagePrototype.clone();
}
^ This is a white lie because you actually can iterate over methods depending on what language you're using, but iterating over an array is still probably a better solution because it's less complex than reflection/introspection.