Prototype Pattern

📢 This article was translated by gemini-3-flash-preview

Prototype Pattern - Creational Pattern

Intent

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

Structure

image

Participants:

  • Prototype: Declares an interface for cloning itself.
  • ConcretePrototype: Implements an operation for cloning itself.
  • Client: Creates a new object by asking a prototype to clone itself.

Applicability

Use the Prototype pattern when:

  • A system should be independent of how its products are created, composed, and represented.
  • The classes to instantiate are specified at run-time, for example, by dynamic loading.
  • You want to avoid building a factory hierarchy that parallels the product hierarchy.
  • Instances of a class can have only one of a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually each time with the appropriate state.

Example 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class main{
    Product p1 = new Product(2023, 3.03);
    System.out.println(p1.getId() + " " + p1.getPrice());

    // Product p2 = new Product(2023, 3.03);
    Product p2 = (Product) p1.Clone();
    System.out.println(p2.getId() + " " + p2.getPrice());
}

interface Prototype{
    public Object Clone();
}

class Product implements Prototype{
    private int id;
    private double price;

    public Product(){}
    public Product(int id, double price){
        this.id = id;
        this.price = price;
    }

    public int getId(){
        return this.id;
    }
    public double getPrice(){
        return this.price;
    }

    public void setId(int id){
        this.id = id;
    }
    public void setPrice(double price){
        this.price = price;
    }

    @Override
    public Object Clone(){
        Product object = new Product();
        object.id = this.id;
        object.price = this.price;
        return object;
    }
}

Example 2 (Using official interface)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class main{
    Product p1 = new Product(2023, 3.03);
    System.out.println(p1.getId() + " " + p1.getPrice());

    // Product p2 = new Product(2023, 3.03);
    Product p2 = (Product) p1.clone();
    System.out.println(p2.getId() + " " + p2.getPrice());
}

// Removed
// interface Prototype{
//     public Object Clone();
// }

// Implement interface
class Product implements Cloneable{
    private int id;
    private double price;

    public Product(){}
    public Product(int id, double price){
        this.id = id;
        this.price = price;
    }

    public int getId(){
        return this.id;
    }
    public double getPrice(){
        return this.price;
    }

    public void setId(int id){
        this.id = id;
    }
    public void setPrice(double price){
        this.price = price;
    }
    
    // Override method
    @Override
    public Object clone(){
        return super.clone();
    }
}