Prototype Pattern

If the cost of creating a new object is high, we clone the object to avoid re-creation. Prototype creates new objects by copying the prototype object.

Prototype addressing the same problem as the Factory Method and Abstract Factory patterns but is more flexible as new prototypes can register themselves with the clients at runtime.

When a client needs to create a set of objects that are almost similar or we want to avoid building numerous factory methods, we use prototype. Prototype creates one object upfront and designates it as a prototype object and creates other objects by simply making a copy of the prototype and making required modifications.

Prototype reduces subclassing because for example, Factory Method often produces a hierarchy of creator classes that parallels the product class hierarchy and this tree of classes can become so big.

Clone is usually a shallow copy wherein the original and the cloned object referring to the same copy of the referenced lower-level object. But we can implement clone method to be a deep copy. In a deep copy, the original top-level object and all of its primitive members are duplicated, any lower-level objects that the top-level object contains are also duplicated so the original and the cloned object refer to two different lower-level objects.

prototype.jpeg

Implementations:
When the number of prototypes in a system isn't fixed (that is, they can be created and destroyed dynamically), keep a registry of available prototypes. Clients won't manage prototypes themselves but will store and retrieve them from the registry. A client will ask the registry for a prototype before cloning it. We call this registry a prototype manager. A prototype manager is an associative store that returns the prototype matching a given key. It has operations for registering a prototype under a key and for unregistering it. Clients can change or even browse through the registry at run-time.

Related Patterns:
An Abstract Factory might store a set of prototypes from which to clone and return product objects.

// shallow
class X implements Cloneable {
public Object clone() {
    try {        //shallow copy
            return super.clone();
      } catch (CloneNotSupportedException e) {
            return null;
      }
}
 
// deep
class X implements Cloneable {
    B b;    //reference to another object
    int i;    //primitive members
    public Object clone() {
        X x= new X(i , b);        //Deep copy of B
        return x;
    }
    public X (int i , B bb) {
        b = new B(bb);//this is a simple example. B can be created in any other way
    }
}

Look at this example:

public interface Plan {
}
public interface AdslPlan extends Plan {
}
public class ContractADSL implements AdslPlan {
}
public interface DialPlan extends Plan {
}
public class HighSpeedADSL implements AdslPlan {
}
public class MonthlyDial implements DialPlan {
}
public class PayAsYouGoDial implements DialPlan {
}
public class PlanPrototype {
 
    Plan monthlyADSL;
    Plan monthlyDial;
    Plan highSpeedADSL;
    Plan payAsYouGoDial;
    Plan contractDial;
    Plan contractADSL;
 
    public PlanPrototype() { //one stupid way of creating prototypes
        monthlyADSL = new MonthlyADSL();
        monthlyDial = new MonthlyDial();
        highSpeedADSL = new HighSpeedADSL();
        payAsYouGoDial = new PayAsYouGoDial();
        contractDial = new ContractDial();
        contractADSL = new ContractADSL();
    }
 
    public Plan getMonthlyADSL() {
        return a clone of MonthlyADSL;
    }
    public Plan getMonthlyDial() {
        return a clone of  MonthlyDial;
    }
    public Plan getHighSpeedADSL() {
        return a clone of  HighSpeedADSL;
    }
    public Plan getPayAsYouGoDial() {
        return a clone of  PayAsYouGoDial;
    }
    public Plan getContractDial() {
        return a clone of  ContractDial;
    }
    public Plan getContractADSL() {
        return a clone of ContractADSL;
    }
}
 
public class Client {
    public static void main(String args[]) {
        PlanPrototype prototype = new PlanPrototype();
        prototype.getContractADSL();
    }
}

Look at another example:

public interface ProductCreator {
    public Product createProduct();    //just an interface for cloning
}
public class AdslProductCreator implements ProductCreator  {
    Product product;
 
    public AdslProductCreator(){
        product = ... //prototype
    }
 
    @Override
    public Product createProduct() {
        ...    //create another product based on the prototype
    }
}
 
public class DialProductCreator implements ProductCreator {
    Product product;
 
    public DialProductCreator(){
        product = ... // create a prototype
    }
 
    @Override
    public Product createProduct() {
        //create a clones from product
    }
}
 
public class Client {
    public static void main(String args[]){
        ProductCreator creator = new DialProductCreator(); // creates the prototype
        Product product1 = creator.createProduct();// create from the prototype
        Product product2 = creator.createProduct();//create another one
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License