Skip to content
On this page

Prototype

Specify the kinds of objects to create using a prototypical instance, and create new objects by copying these prototypes.

The Prototype pattern refers to creating new objects based on an existing prototype.

Let's consider an example: if we already have a String[] array and want to create another identical String[] array, how would we do it?

In reality, the creation process is straightforward—it involves copying the elements of the existing array to a new array. If we encapsulate this creation process, it becomes the Prototype pattern. Here's how to implement it in code:

java
// Prototype:
String[] original = { "Apple", "Pear", "Banana" };
// New object:
String[] copy = Arrays.copyOf(original, original.length);

For ordinary classes, how do we achieve prototype copying? Java's Object provides a clone() method intended for copying a new object. We need to implement the Cloneable interface to mark an object as "cloneable":

java
public class Student implements Cloneable {
    private int id;
    private String name;
    private int score;

    // Clone and return a new object:
    @Override
    public Object clone() {
        Student std = new Student();
        std.id = this.id;
        std.name = this.name;
        std.score = this.score;
        return std;
    }
}

When using it, because the clone() method's signature is defined in Object, and the return type is also Object, casting is required, which is somewhat cumbersome:

java
Student std1 = new Student();
std1.setId(123);
std1.setName("Bob");
std1.setScore(88);
// Clone a new object:
Student std2 = (Student) std1.clone();
System.out.println(std1);
System.out.println(std2);
System.out.println(std1 == std2); // false

In practice, a better way to use the Prototype pattern is to define a copy() method that returns a clearly typed object:

java
public class Student {
    private int id;
    private String name;
    private int score;

    public Student copy() {
        Student std = new Student();
        std.id = this.id;
        std.name = this.name;
        std.score = this.score;
        return std;
    }
}

The Prototype pattern is not widely used because many instances hold resources like files or sockets, which cannot be shared by copying to another object. Only "value" objects that store simple types can be copied.

Practice

Add a clone() method to the Student class.

java
public class Student implements Cloneable {
    private int id;
    private String name;
    private int score;

    // Getters and setters omitted for brevity

    @Override
    public Object clone() {
        try {
            return (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            // Handle exception or return a new instance
            return new Student(this.id, this.name, this.score);
        }
    }

    // Constructor for cloning
    public Student(int id, String name, int score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }
}

Example Usage:

java
public class Client {
    public static void main(String[] args) {
        Student std1 = new Student(123, "Bob", 88);
        // Clone a new object:
        Student std2 = (Student) std1.clone();
        System.out.println(std1); // Output: Student@1a2b3c4
        System.out.println(std2); // Output: Student@5d6e7f8
        System.out.println(std1 == std2); // false
    }
}

Summary

The Prototype pattern creates a new instance by copying an existing object instance, ensuring that the copied object's type and properties are identical to the original instance.

Key Points

  • Cloning Existing Objects: Utilize existing instances as prototypes to create new objects through copying.
  • Implementing Cloneable: In Java, implement the Cloneable interface and override the clone() method to enable object cloning.
  • Defining Clear Copy Methods: Prefer defining a copy() method with a clear return type over using clone() to avoid cumbersome casting and improve type safety.
  • Limitations: The Prototype pattern is best suited for simple "value" objects. It is less applicable for objects that manage complex resources like files or network connections, which cannot be easily or safely cloned.

The Prototype pattern is particularly useful when the cost of creating a new object is expensive, and a copy of an existing object can be used as a starting point.

Prototype has loaded