Prototype Pattern

Last Updated on September 24, 2023 by KnownSense

The Prototype pattern is a creational design pattern that focuses on creating new objects by copying an existing object, called the prototype, rather than using constructors. This pattern is particularly useful when creating objects that are similar to existing ones, as it promotes code reusability and reduces the overhead of repeatedly initializing objects from scratch.

There are multiple scenarios where the Prototype pattern is useful:

  • Creating objects with multiple configurations, where existing objects can be used as templates.
  • Cloning objects with intricate initialization processes, such as those involving database connections or network calls.
  • Designing frameworks where clients create their own classes by extending existing prototypes.

Benefits

  1. Reduced Overhead: Creating new objects by copying existing ones is often more efficient than initializing objects from scratch, especially if the initialization process is complex.
  2. Flexibility: The Prototype pattern supports creating new object instances at runtime, which can be useful when the exact type of object needed isn’t known until runtime.
  3. Code Reusability: Objects can be easily reused by cloning existing prototypes, reducing the need to create multiple constructor overloads for different object configurations.
  4. Customization: Cloned objects can be modified without affecting the original prototypes, allowing for customization while maintaining a common foundation.
  5. Hides Implementation Details: The Prototype pattern abstracts the cloning process and object creation from the client code, promoting separation of concerns.

UML for Prototype

 Prototype Pattern

Implementation

Imagine you’re developing a coffee shop application that allows customers to create customized coffee orders. Each coffee order might have multiple components like size, type of coffee, and additional toppings. Using the Prototype design pattern, you can create a prototype object for a basic coffee order and then clone it to create customized versions.

Step1: Create a interface Prototype with method getClone

public interface Prototype {

    Prototype getClone();
}

Step2: Create a concrete class CoffeeOrder which implements the Protoype interface

public class CoffeeOrder implements Prototype {
    private String size;
    private String coffeeType;
    private List<String> toppings;

      // Constructor
    public CoffeeOrder(String size, String coffeeType) {
        this.size = size;
        this.coffeeType = coffeeType;
        this.toppings = new ArrayList<>();
    }

      // Method to add toppings
    public void addTopping(String topping) {
        toppings.add(topping);
    }

    public String getSize() {
        return size;
    }
    public String getCoffeeType() {
        return coffeeType;
    }
    public List<String> getToppings() {
        return toppings;
    }

      //Clone method
    @Override
    public Prototype getClone()  {
        CoffeeOrder clonedOrder = new CoffeeOrder(size,coffeeType);
          //Deep copy the toppings list
        clonedOrder.toppings = new ArrayList<>(this.toppings);
        return clonedOrder;
    }

}

Step3: In main class, create a prototype coffee order, and clone the prototype to create customized orders

public class CoffeeShopApp {
    public static void main(String[] args) {
        // Create a prototype coffee order
        CoffeeOrder prototypeOrder = new CoffeeOrder("Medium", "Latte");
        prototypeOrder.addTopping("Whipped Cream");


            // Clone the prototype to create customized orders
            CoffeeOrder order1 = (CoffeeOrder) prototypeOrder.getClone();
            order1.addTopping("Caramel Drizzle");

            CoffeeOrder order2 = (CoffeeOrder) prototypeOrder.getClone();
            order2.addTopping("Chocolate Syrup");

            // Display the orders
            System.out.println("Order 1: " + order1.getSize() + " " + order1.getCoffeeType() +
                    " with " + order1.getToppings());
            System.out.println("Order 2: " + order2.getSize() + " " + order2.getCoffeeType() +
                    " with " + order2.getToppings());
    }
}

OUTPUT:
Order 1: Medium Latte with [Whipped Cream, Caramel Drizzle]
Order 2: Medium Latte with [Whipped Cream, Chocolate Syrup]

Note: In above example instead of creating Prototype interface, we can use interface java.lang.Cloneable.

Conclusion

The Prototype design pattern in Java offers efficient object creation through cloning, enabling customization and reducing complexity. It involves implementing Cloneable and clone() to create copies of objects, making it useful for managing complex object hierarchies and maintaining isolated instances with options for deep or shallow copying.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top