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
Prototype results in a cloned object which is different from the original object. The state of the original is the same as the clone, at the time of cloning. Thereafter each object may undergo state change. You can think of this as something similar photocopying the original and then modifying the photocopy at a few places.
Example
Benefits
MemberwiseClose()
to perform a deep copy.When to use it
Comparison with Factory Pattern
Prototype pattern allows an object to create customized objects without knowing their class or any details of how to create them. So, it is this aspect it appears to be a lot like the Factory Method pattern. In both these patterns, the client can create any of the derived class objects without knowing anything about their own structure.
But the difference between the two patterns is the fact that for the Factory Method
concentrates on creating one object of a non existing object type as a fresh creation
(by understanding the exact sub-type of the Creator class). The Prototype
pattern uses the class itself, especially the derived class for self duplication
action.
In this pattern, the client (or consumer) asks the Creator (or factory) for a specific type of object from a class hierarchy. The Creator method of the factory class delegates the creation of the specific object to the derived classes and return the object of the class of the type asked by client. In essence, you have a single point of contact for the creation of several objects of a class hierarchy.
You can think of this as going to a airline ticket counter (controller) and asking for a ticket by giving your preference of the ticket type (first class, executive or economy). The user is not concerned with how the ticket is being generated, even though in an object representation the first class and the economy ticket are both derived from the base ticket class.
When to use
A specific Factory class already exists. But the Factory will have slightly varying methods. Each method can produce an instance. The client can choose appropriate method and get the instance.
If you take the example of MVC based perfect Architectural Design, the client will be a Business Controller Class while Concrete Products will all be Business Entities. The Factories are Auxiliary ( Helper) Controllers. They work in association with a request from the Business Controller.
When to use
The gain in efficiency of using a prototype is questionable in my mind. There will be no efficiency gain because in most languages the clone method itself executes a call to new in order to construct a new object instance of itself.
The only benefit that I see in using the prototype pattern is one of convenience, you know that clone will give you an exact copy of the object which frees you from having to set the attributes of the new object to the same values yourself and possibly struggling with deep copy.
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.