- Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.
- This pattern is used to:
- Avoid sub-classes of an object creator in the client application, like the factory method pattern does.
- Avoid the inherent cost of creating a new object in the standard way (like using the 'new') when it is expensive for a given application.
- Prototype design pattern hides object creation from the client.
- However, instead of creating a non-initialized object, it returns a new object that is initialized with values it copied from a prototype - or sample - object.
- The Prototype design pattern is not commonly used in the construction of business applications.
- The Prototype design pattern creates clones of pre-existing sample objects.
- Prototype pattern can be found in object serialization scenarios.
- Let’s say you have a prototypical object that has been serialized to persistent storage, such as, disk or a database.
- Having this serialized representation as a prototype you can then use it to create copies of the original object.
Cloning Types
- There are two different types of cloning: deep copy & shallow copy.
- Shallow copy is easier but only copies data fields in the object itself and not the objects the prototype refers to.
- Deep copy copies the prototype object and all the objects it refers to.
- The best way to implement this in .NET is to use the built-in
ICloneable
interface on the objects that are used as prototypes.
- The
ICloneable
interface has a method called Clone that returns an object that is a copy, or clone, of the original object.
Participants
Prototype
(ICloneableModel)
- Declares an interface for cloning itself,
ConcretePrototype
(Model)
- Implements an operation for cloning itself.
var mainModel = new Model
{
Data = 1
};
var copyModel = mainModel.Clone() as Model;
public interface ICloneableModel
{
ICloneableModel Clone();
}
public class Model : ICloneableModel
{
public int Data { get; set; }
public ICloneableModel Clone() => MemberwiseClone() as ICloneableModel;
}
Rules of Thumb
- Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
- Factory Method: creation through inheritance.
- Factory Method requires sub-classing, but doesn't require Initialize.
- Prototype: creation through delegation.
- Prototype doesn't require sub-classing, but it does require an "initialize" operation.
- Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.
- Prototype co-opts one instance of a class for use as a breeder of all future instances.
- Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters.
- In this context, Prototype can avoid expensive "creation from scratch", and support cheap cloning of a pre-initialized prototype.
- Prototype is unique among the other creational patterns in that it doesn't require a class but only an object.
- Object-oriented languages like Self and Omega that do away with classes completely rely on prototypes for creating new objects.