Prototype
(→Liabilities) |
(→Example) |
||
(11 intermediate revisions by 2 users not shown) | |||
Line 33: | Line 33: | ||
− | + | === Another Example === | |
+ | You can find a nicely explained java code example of the Prototype Pattern [http://java.dzone.com/articles/design-patterns-prototype here] | ||
==Consequences== | ==Consequences== | ||
Line 41: | Line 42: | ||
==Liabilities== | ==Liabilities== | ||
− | * Implementing the Clone() method can be difficult, especially when the internal objects of the products don't support copying or there are circular references that complicate copying. The question is do we want our cloned object to share the pointer with it's original object or do we want for a cloned object to have its own instance variable.Also what is going to happen to subobjects that original contains, are we cloning containing objects by clonning the parent object? If the clone and original share the pointer then we say that the clone is | + | * Implementing the Clone() method can be difficult, especially when the internal objects of the products don't support copying or there are circular references that complicate copying. The question is do we want our cloned object to share the pointer with it's original object or do we want for a cloned object to have its own instance variable.Also what is going to happen to subobjects that original contains, are we cloning containing objects by clonning the parent object? |
− | In c# for example there is a | + | There are two options: |
− | If our clone object has a seperate instance of a variable then we are talking about | + | # If the clone and original share the pointer then we say that the clone is '''[[Shallow_VS_Deep_Copy|Shallow Copy]]''' of its original.In c# for example there is a built-in method called ''MemberwiseClone'' which is available on all objects. It copies the ''values'' of the immediate fields and references that the object contains, and returns a reference to this copy. It does not copy what the references in the object point to. |
+ | (Probably the name ''MemberwiseClone'' should refer to deep coping not shallow as Deep Copy is also known as Memberwise copy. --[[User:Mujtaba Alshakhouri|Mujtaba Alshakhouri]]) | ||
+ | # If our clone object has a seperate instance of a variable then we are talking about '''[[Shallow_VS_Deep_Copy|Deep Copy]]'''. In this case our cloned object would contain the copies of all underlining objects that the original object contained. This can be achived by using process called [[serialization]].Serializing an object structure is possible only if all referenced objects are serializable.The easiest way of using serialization for prototype purposes is to store serialized object in memory buffer and then deserialize it from there. | ||
+ | |||
+ | c# code example of ConcretePrototype class (both shallow and deep copy) | ||
+ | |||
+ | # using System; | ||
+ | # using System.Collections.Generic; | ||
+ | # using System.Runtime.Serialization; | ||
+ | # using System.Runtime.Serialization.Formatters.Binary; | ||
+ | # | ||
+ | # namespace PrototypePattern { | ||
+ | # // Prototype Pattern Judith Bishop Nov 2007 | ||
+ | # // Serialization is used for the deep copy option | ||
+ | # // The type T must be marked with the attribute [Serializable( )] | ||
+ | # | ||
+ | # [Serializable( )] | ||
+ | # public abstract class IPrototype <T> { | ||
+ | # | ||
+ | # // Shallow copy | ||
+ | # public T Clone( ) { | ||
+ | # return (T) this.MemberwiseClone( ); | ||
+ | # } | ||
+ | # | ||
+ | # // Deep Copy | ||
+ | # public T DeepCopy( ) { | ||
+ | # MemoryStream stream = new MemoryStream( ); | ||
+ | # BinaryFormatter formatter = new BinaryFormatter( ); | ||
+ | # formatter.Serialize(stream, this); | ||
+ | # stream.Seek(0, SeekOrigin.Begin); | ||
+ | # T copy = (T) formatter.Deserialize(stream); | ||
+ | # stream.Close( ); | ||
+ | # return copy; | ||
+ | # } | ||
+ | # } | ||
+ | # } | ||
==Related Patterns== | ==Related Patterns== |
Latest revision as of 07:08, 20 October 2010
Contents |
Intent
The Prototype pattern allows you to specify what objects you want to create once, and then create new ones by copying a prototype object.
Structure
The Prototype class declares the clone() method, which is implemented by all subclasses as a way to return a copy of itself. Each Client is instantiated with an equivalent Prototype class, it creates a new Prototype object by telling it's Prototype to clone itself.
Usage
The Prototype pattern should be used when a system needs to be independent of how it's products are created, composed and represented. AND:
- When the classes to instantiate are specified at run time, OR
- To avoid building parallel hierarchies of factories and products, OR
- When an instance of a class can be only one of a few different states. The Prototype pattern may be more convenient than instantiating the class manually each time with the appropriate state.
Example
A good example for this pattern is given in the Gang of Four Design Patterns book. They describe a music score editor, which is built by adding music objects such as Notes and Staves to a graphical editor framework. The graphical editor also has Tools for manipulating Graphic objects, such as selecting, moving etc. There must also be a way to create Graphic objects and add them to the editor, which they call GraphicTool which is a subclass of Tool. The example diagram from the book is below:
The GraphicTool class creates a problem. It is part of the graphical editor framework, and doesn't know how to create music objects such as Notes and Staves etc. One solution would be to create sublcasses of GraphicTool for each music object that we need to create, however these subclasses would only differ in the type of music object that they create. This would also create the Parallel hierarchies problem.
The solution is to make the GraphicTool create a new Graphic by "cloning" an instance of a subclass of Graphic. This cloned instance is called a prototype. Each GraphicTool object is initialized with the prototype that it is designated to create. Each GraphicTool instance will add it's music object to the score by cloning it's prototype and adding the clone to the score. The GraphicTool class can clone any type of Graphic as long as all Graphic subclasses support the clone() method.
Another Example
You can find a nicely explained java code example of the Prototype Pattern here
Consequences
- Hides the concrete product classes from the client, reducing the number of classes that clients need to know about. This adds flexibility and means that new products can be added without affecting clients.
- New products can be added and removed at runtime by simply creating a new prototype for clients to copy.
- There is no need for the Creator class hierarchy as there is with other patterns like Factory Method.
Liabilities
- Implementing the Clone() method can be difficult, especially when the internal objects of the products don't support copying or there are circular references that complicate copying. The question is do we want our cloned object to share the pointer with it's original object or do we want for a cloned object to have its own instance variable.Also what is going to happen to subobjects that original contains, are we cloning containing objects by clonning the parent object?
There are two options:
- If the clone and original share the pointer then we say that the clone is Shallow Copy of its original.In c# for example there is a built-in method called MemberwiseClone which is available on all objects. It copies the values of the immediate fields and references that the object contains, and returns a reference to this copy. It does not copy what the references in the object point to.
(Probably the name MemberwiseClone should refer to deep coping not shallow as Deep Copy is also known as Memberwise copy. --Mujtaba Alshakhouri)
- If our clone object has a seperate instance of a variable then we are talking about Deep Copy. In this case our cloned object would contain the copies of all underlining objects that the original object contained. This can be achived by using process called serialization.Serializing an object structure is possible only if all referenced objects are serializable.The easiest way of using serialization for prototype purposes is to store serialized object in memory buffer and then deserialize it from there.
c# code example of ConcretePrototype class (both shallow and deep copy)
- using System;
- using System.Collections.Generic;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- namespace PrototypePattern {
- // Prototype Pattern Judith Bishop Nov 2007
- // Serialization is used for the deep copy option
- // The type T must be marked with the attribute [Serializable( )]
- [Serializable( )]
- public abstract class IPrototype <T> {
- // Shallow copy
- public T Clone( ) {
- return (T) this.MemberwiseClone( );
- }
- // Deep Copy
- public T DeepCopy( ) {
- MemoryStream stream = new MemoryStream( );
- BinaryFormatter formatter = new BinaryFormatter( );
- formatter.Serialize(stream, this);
- stream.Seek(0, SeekOrigin.Begin);
- T copy = (T) formatter.Deserialize(stream);
- stream.Close( );
- return copy;
- }
- }
- }
Related Patterns
- Abstract Factory: This pattern is very similar to Prototype and is used in similar situations. Abstract Factory can also be combined with Prototype, with factories using prototypes to create product objects.
- Composite and Decorator: Designs that use these patterns can often benefit from using Prototype to instantiate objects.
See also
Design patterns | |
---|---|
Creational: Abstract Factory | Builder | Factory Method | Prototype | Singleton |