Prototype

Specify the kinds of objectsto create using a prototypical instance, and create new objects by copying this prototype.

Introduction

  • Prototype is a design pattern belonging to the Creational Pattern group - design patterns for initializing class objects.

  • Prototype specifies the type of objects to be created using a template object, created by copying this template object without making code dependent on their classes.

  • Prototype Pattern is used when creating an object is costly and time-consuming when you already have a similar object that exists.

  • Prototype Pattern provides a mechanism to copy from the original object to a new object and change the value of some properties if necessary.

  • Frequency of use: medium

Problem

Say you have an object, and you want to create an exact copy of it. How would you do it? First, you have to create a new object of the same class. Then you have to go through all the fields of the original object and copy their values over to the new object.

Nice! But there’s a catch. Not all objects can be copied that way because some of the object’s fields may be private and not visible from outside of the object itself.

There’s one more problem with the direct approach. Since you have to know the object’s class to create a duplicate, your code becomes dependent on that class. If the extra dependency doesn’t scare you, there’s another catch. Sometimes you only know the interface that the object follows, but not its concrete class, when, for example, a parameter in a method accepts any objects that follow some interface.

Solution

The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object. Usually, such an interface contains just a single clone method.

The implementation of the clone method is very similar in all classes. The method creates an object of the current class and carries over all of the field values of the old object into the new one. You can even copy private fields because most programming languages let objects access private fields of other objects that belong to the same class.

An object that supports cloning is called a prototype. When your objects have dozens of fields and hundreds of possible configurations, cloning them might serve as an alternative to subclassing.

Here’s how it works: you create a set of objects, configured in various ways. When you need an object like the one you’ve configured, you just clone a prototype instead of constructing a new object from scratch.

Structure

Basic implementation

Components in the model:

  • Prototype: declares an object for its copying.

  • ConcretePrototype: executes an operation for its replication.

  • Client: creates a new object by requesting a model for its copy. Avoid creating multiple subclasses for each object created like the Abstract Factory Pattern.

Reduces the cost to create a new "standard" object, meaning this increases Performance compared to using the new keyword to create a new object.

To implement the Prototype Pattern, create a Clone() Method in the superclass, and implement it in the subclasses. There are 2 types of cloning in Prototype:

  • Shallow copy: Child objects inside can only copy references. This means that the value type can only be cloned. (The original object and the newly created object both point to the same internal child object)

  • Deep copy: The child objects inside also have all their properties copied. This means duplicating the value type and reference type.

Prototype registry implementation

Pros and Cons

Pros

  • Add and remove concrete classes at run-time: The prototype integrates the process of instantiating a new object into the system simply by registering a prototype instance with the client. That's a bit more flexible than other constructor patterns because the client can install and remove primitives at run-time.

  • Create a new object by changing some of the object's attributes (objects with few differences): A flexible system will let us define a certain action through association with an object ( meaning a method of a class) rather than defining a new class. The client can express a different effect by delegating to the prototype class. At the same time, this initialization method also helps us declare a "new class" without having to do any programming. In fact, copying a prototype is like instantiating an object from a new class. Prototype pattern helps reduce the number of layers a system needs to use.

  • Initializing new objects by changing the structure: Many applications build systems from many parts and sub-parts. Subparts are initialized from many other subparts (divide the problem). The prototype pattern also supports this. That means those parts can be instantiated by copying a prototype from another "structure". As long as the combined parts both instantiate Clone() and are used with different constructs as prototypes.

  • Reduce subclassing: Sometimes the system is too complex because there are too many classes, and the inheritance tree of the initializing class has too many parallel classes at the same level. The prototype pattern clearly reduces the number of classes and the complexity of the class hierarchy. One limitation of the prototype pattern is that sometimes having to implement each Clone() method of each subclass of Prototype will be difficult. For example, implementing Clone() will be difficult when their internal objects do not support copying or have a reference that cannot be copied.

Cons

  • Cloning complex objects that have circular references might be very tricky.

When to use

  • Like other constructivist design patterns (Builder, Abstract Factory, and Factory Method), the Prototype design pattern hides object creation from the client. However, instead of creating an object that is not set, it returns a new object that is set with the values it copied from a model object.

  • The Prototype design pattern is not commonly used in building business applications. It is commonly used in certain types of applications such as computer graphics, CAD (Computer Assisted Drawing), GIS (Geographic Information Systems), and games.

  • The Prototype design pattern creates copies of pre-existing prototype objects. The best way to do this in .NET is to use the ICloneable interface available on objects used as prototypes. The ICloneable interface has a method called Clone that returns an object that is a copy of the original object.

  • When performing the Clone function, you need to pay attention to two different types: deep copy and shallow copy. Shallow copy is easier but only copies the data fields in the object itself – not the objects the model exposes. Deep copy copies the model object and all its exposed objects. Shallow copy is easy to implement because the Object class has a MemberwiseClone method that returns a shallow copy of the object. The replication strategy for deep copy can be more complex – some objects are not easily copied (such as Threads, database connections, …).

  • Flexibility thanks to the multiplexing of the clone() method, we can create a new object without needing to write code that specifically calls the constructor function (if we need to specifically create a certain type, we assign to other preprocessing processes, and these preprocessing processes probably do not depend on the specific constructor, again we are freed...)

  • Avoid creating multiple subclasses for each object like the Abstract Factory Pattern

  • Significantly reduces costs compared to creating an object using the standard method, calling the new operator (calling a specific constructor)

  • We can customize the sample object properties to create new sample objects. Or it can be understood that we create a new "standard" class from an existing class without having to write code to define it.

  • There are also many other benefits from the Design pattern: Prototype that we can apply in programming.

Relations with Other Patterns

  • Many designs start by using Factory Method (less complicated and more customizable via subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more complicated).

  • Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes.

  • Prototype can help when you need to save copies of Commands into history.

  • Designs that make heavy use of Composite and Decorator can often benefit from using Prototype. Applying the pattern lets you clone complex structures instead of re-constructing them from scratch.

  • Prototype isn’t based on inheritance, so it doesn’t have its drawbacks. On the other hand, Prototype requires a complicated initialization of the cloned object. Factory Method is based on inheritance but doesn’t require an initialization step.

  • Sometimes Prototype can be a simpler alternative to Memento. This works if the object, the state of which you want to store in the history, is fairly straightforward and doesn’t have links to external resources, or the links are easy to re-establish.

Last updated