Design patterns in the test of timePrototype
Create objects based on a template of an existing object through cloning.
This is how it looks like:
Surprisingly enough, there are very few useful concrete examples of this, even in the literature. A lot of the time you see reference to ConcreteImplA and ConcreteImplB.
The original impetus for the Prototype pattern was actually:
- avoid subclasses of an object creator in the client application, like the abstract factory pattern does.
- avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application.
That is actually quite interesting. As I mentioned in the Factory Method analysis post, I like the notion of using Factory Delegate (and thus avoiding subclassing) quite a lot. This is usually useful for behavioral objects, that contains little state (it would be more accurate to say that their state is behavior, such as a class that mostly contains delegate members for different things). But for those sort of things, you usually don’t really need to modify them after the fact, so there isn’t much of a prototype here.
The second reasoning is not relevant for most things today. The cost of new is so near zero to be effectively meaningless.
But something that isn’t mentioned about this pattern is that it is very useful for multi threading. The notion of being able to handle a cloned object that can be modified independently of its original is key in things like caches, as you can see in the code above. We make heavy use of that internally inside RavenDB, for example, although we choose a slight more complex (and performant) route.
A key observation about this is that Prototype assumes long lives objects. Because otherwise, there wouldn’t be the prototype instance to clone from. In wide variety of applications today, that is simply not the case. Most of our objects live only for a single request. And anything whose lifetime is longer than a single request is usually persisted to a stable storage, rendering the basis for the Prototype pattern existence moot.
Recommendation: This is still a useful pattern for a limited number of scenarios. In particular, the ability to hand out a copy of the instance from a cache means that we don’t have to worry about multi threading. That said, beyond this scenario, I haven’t found many other uses for this.
More posts in "Design patterns in the test of time" series:
- (21 Jan 2013) Mediator
- (18 Jan 2013) Iterator
- (17 Jan 2013) Interpreter
- (21 Nov 2012) Command, Redux
- (19 Nov 2012) Command
- (16 Nov 2012) Chain of responsibility
- (15 Nov 2012) Proxy
- (14 Nov 2012) Flyweight
- (09 Nov 2012) Façade
- (07 Nov 2012) Decorator
- (05 Nov 2012) Composite
- (02 Nov 2012) Bridge
- (01 Nov 2012) Adapter
- (31 Oct 2012) Singleton
- (29 Oct 2012) Prototype
- (26 Oct 2012) Factory Method
- (25 Oct 2012) Builder
- (24 Oct 2012) A modern alternative to Abstract Factory–filtered dependencies
- (23 Oct 2012) Abstract Factory
Comments
Hi, actually I found immutable objects (doing functional style in .Net) quite useful. As I see once you have immutable-s (like a horrible immutable App Viewmodel :-) ) cloning comes into the picture naturally (ok in case of simple regeneration of the immutable sub trees changed). Also to make say something about .Net support there's MemberwiseClone method and ICloneable interface.
Cheers, Miklos
How about in the implementation of move semantics for C++ 11?
I have found two uses for this pattern in production. Both have to do with retaining identity while specifying the object you want by example.
The first example is object recycling. In Update Controls, a dependency-tracking MVVM framework, you specify a dependent collection using Linq. When the results change -- for example one object is added to the collection -- the entire query is re-run. Update Controls will compare the results of the query to the objects already in the list, and recycle those that are equal. This lets it figure out what has been inserted, deleted, or reordered while still retaining the identity of the untouched objects. This keeps data-bound lists from scrolling to the top or losing their selection. The query results are used as a prototype.
The second example is persistence identity. In Correspondence, a collaboration framework, you call a method to persist an object. If that object already exists, then the existing one is returned. If not, it returns the parameter. By using the parameter as a prototype, this method retains the identity of an object in memory, relative to the object on disk.
Retaining identity is important. The prototype pattern accomplishes that.
Prototype pattern can also be combined along with AbstractFactory to create objects.
I think the Prototype pattern is generally useful with mutable objects of all kind, not only in multithreading environments. It basically enables you to make a protective copy when a mutable object is exchanged between a caller and a callee. The advantage of the prototype pattern is then that the protective copy is controlled by the original object, i.e. it defines the class of the object to create as well as all details (shallow clone, deep clone etc). You can't have so much control with other creational patterns.
On the cons side, implementing Cloneable creates an obligation for any sub class, so it should be used with care.
The Java "Properties" class is a prototype I believe. You also have prototype based languages such as Java, Lua and Io - in these there is no differentiation between a class and an object, as a 'class' is just a prototype which is used to create a new object.
Comment preview