Friday, May 20, 2011

Prototype pattern

Prototype Pattern allows you to make new instances by copying the existing instances.

Key aspect of this pattern is that the client code can make new instances without knowing which specific class is being instantiate.

When to use Prototype Pattern?

  1. Use Prototype Pattern when creating an instance of a given class is either expensive or complicated (or) when a system must create new objects of many types in a complex class hierarchy.
  2. When there are many subclasses that differ only in the kind of objects, A system needs independent of how its objects are created, composed, and represented.

Rather than creating more instances,you make copies of the original instance,modifying them as appropriate.
Prototypes can also be used whenever we need classes that differ only in the type of processing they offer,for example in parsing of strings representating numbers in diff radixes.In this sense prototype is nearly the same as Examplar pattern described in Coplien[1992].

Prototype Pattern vs Other patterns

Prototype pattern may look similar to builder design pattern. There is a huge difference to it. If you remember, “the same construction process can create different representations” is the key in builder pattern. But not in the case of prototype pattern.

How to implement Prototype Pattern

You just have to copy the existing instance in hand. When you say copy in java, immediately cloning comes into picture. Thats why when you read about prototype pattern, all the literature invariably refers java cloning.

"Copy Constructor" is one form of Prototype pattern.

Simple way is, clone the existing instance in hand and then make the required update to the cloned instance so that you will get the object you need. Other way is, tweak the cloning method itself to suit your new object creation need. Therefore whenever you clone that object you will directly get the new object of desire without modifying the created object explicitly.

The prototype design pattern mandates that the instance which you are going to copy should provide the copying feature. It should not be done by an external utility or provider.

But the above, other way comes with a caution. If somebody who is not aware of your tweaking the clone business logic uses it, he will be in issue. Since what he has in hand is not the exact clone. You can go for a custom method which calls the clone internally and then modifies it according to the need. Which will be a better approach.

Always remember while using clone to copy, whether you need a shallow copy or deep copy. Decide based on your business needs. If you need a deep copy, you can use serialization as a hack to get the deep copy done. Using clone to copy is entirey a design decision while implementing the prototype design pattern. Clone is not a mandatory choice for prototype pattern.

In prototype pattern, you should always make sure that you are well knowledgeable about the data of the object that is to be cloned. Also make sure that instance allows you to make changes to the data. If not, after cloning you will not be able to make required changes to get the new required object.

Example

Let's consider the case of an extensive database where we need to make a number of queries to construct an answer.Once we have this answer as a table or ResultSet,we might like to manipulate it to produce other answers without issuing additional queries.

Participants in Prototype design

Prototype: Declares an interface for cloning itself.
Concrete Prototype: Implements an operation for cloning itself.
Client: Creates a new object by asking a prototype to clone itself.
We would lose the advantage of Polymorphism that the GoF formulation of the Prototype pattern gives you. - NatPryce.
Prototype means making a clone.This implies cloning of an object to avoid creation.If the cost of creating a new object is large and creation is resource intensive,we clone the object.We use the interface Cloneable and call its method clone() to clone the object.
One thing we cannot use the clone as it is.We need to instantiate the clone before using it.This can be a performance drawback.This also gives sufficient access to the data and methods of the class.This means that data access methods have to be added to the protoype once it has been cloned.
Alternative To the Flyweight pattern is prototype pattern which allows polymorphic copies of existing objects.The object clone() method signature provides support for Prototype pattern.

Prototypes are useful when object initialization is expensive,and you anticipate few variations on the initialization parameters.Then we could keep already-initialized objects in a table,and clone an exisiting object instead of expensively creating a new one from scratch.
Immutable objects can be returned directly when using Prototyping,avoiding the copying overhead.
Recall,that the idea of prototype is that we are passed an object and use that object as a template to create a new object and use that object as a template to create a new object.Because we might not know the implementation details of the object,we cannot create a new instance of the object and copy all of its data.(Some of the data may not be accessible via methods.) So we ask the object itself to give a copy of itself.

Java provides a simple interface named Cloneable that provides an implementation of the Prototype pattern.If we have an object that is Cloneable,we can call its clone() method to create a new Instance of the object with the same values.

Note that,Cloneable is a marker interface.It merely acts as a tag to state that we really want instance of the class to be cloned. If we don't implement Cloneable,the super.clone() method will throw CloneNotSupportedException.
The object implementation of clone() performs a shallow copy of the object in question.That is,it copies the values of the fields in the object,but not any actual objects that may be pointed to.In other words,the new object will point to the same objects the old object pointed to.

clone() method always retuns an object of type Object.we must cast it to the actual type of the object we are cloning.There are other significant restrictions on the clone method. See here for restrictions.

Please remember clone() method is a shallow copy of the original class.In other words,references of the data objects are copies,but they refer to the same underlying data.Thus any operation we perform on the copied data will also occur on the original data in the Prototype class.
In some cases,this shallow copy is acceptable,but if you want to make a deep copy of the data ,there is a clever trick using the serializable interface.A class is said to be serializable,if we can write it out as a stream of bytes and read those bytes back in to reconstruct the class.This is how RMI is implemented.

Example code for Prototype Pattern in java

Interface:

public interface Cloneable {
public Object clone();
}

 

Concrete Implementation of Cloneable:

I am providing only name and manufacturer for car, to make it simple. There can be other attributes as well like price, engine etc.

public class Car implements Cloneable {

private final String name;
private final String manufacturer;

public Car(String name, String manufacturer) {
this.name = name;
this.manufacturer= manufacturer;
}

@Override
public Object clone() {
Car clone = new Car(name, manufacturer);
return clone;
}

public String getName() {
return name;
}

public String getManufacturer() {
return manufacturer;
}

}



 

Using the Prototype pattern:

 


public class PrototypeMain {

public static void main(String[] args) {
// Let make maruti suzuki
Car marutiSuzuki=new Car("1000","Maruti Suzuki");
Car audiQuattro = new Car("Quattro","Audi");
// We can add more but let's stop here.
//Let's do pattern and not cars :)
//Lets gift our Audi clone to some fried :P
Car clone = (Car) audi.clone();

if (clone.getManufacturer() == "Audi") {
System.out.println("Thanks to Prototype Pattern");
}
}
}





Advantages of Prototype Pattern



  • Adding and removing products at runtime.

  • Specifying new objects by varying values.

  • Specifying new objects by varying structure.

  • Reduced subclassing.

  • Configure an application with classes dynamically.

  • Hides the complexities of making new instances from the client.

  • Provides the option for the client to generate objects whose type is unknown.

  • In some circumstances,copying an object is more efficient than creating a new object.

Consequences of Prototype Pattern



  • Classes that have circular references to other classes cannot really be cloned.

  • One Difficulty in implementing the Prototype Pattern in Java is that if the classes already exist,we may not be able to change them to add the required clone or deepClone methods.The deepClone() method can be difficult if all the class objects contained in the class cannot be declared to implement Serializable.

  • Finally idea of having prototype classes to copy implies that we have sufficient access to the data or methods to these prototype classes so that we can modify the data once we have cloned the class.

Disadvantages


Drawback to using the Prototype is that making a copy of an object can sometimes be complicated.

No comments:

Post a Comment

Chitika