Skip to content

Demystifying the Prototype Design Pattern in Java

Posted on:September 5, 2022 at 01:13 PM

In this blog post, we’ll dive into the Prototype Design Pattern in Java. The Prototype Design Pattern allows us to create copies of existing objects reliably. This proves particularly useful when we need to clone a specific object without dealing with the intricacies of its implementation.

Table of contents

Open Table of contents

Sections

Core Concepts

The fundamental idea behind the Prototype Design Pattern is to provide a reliable way to clone existing objects. This avoids dependencies on specific class implementations, focusing instead on copying the object. The pattern is generally based on a single interface, defining a clone method to create multiple clones of a prototype through a consistent interface.

The Vehicle Example

To illustrate the Prototype Design Pattern, we’ll use a hypothetical scenario involving vehicles. We’ll consider a Vehicle abstract class with key attributes like wheels and price. Our objective is to clone objects of classes extending Vehicle without exposing their implementation details.

Vehicle Class

// [Apartment.java]
public abstract class Vehicle {
    protected int wheels;
    protected long price;

    public Vehicle() { }

    public Vehicle(Vehicle target) {
        if (target != null) {
            this.wheels = target.wheels;
            this.price = target.price;
        }
    }

    public abstract Vehicle clone();

    public abstract boolean isClone(Vehicle target);
}

Car Class

public class Car extends Vehicle {
    private String color;

    public Car(int wheels, long price, String color) {
        this.wheels = wheels;
        this.price = price;
        this.color = color;
    }

    public Car(Car target) {
        super(target);
        if (target != null) {
            this.color = target.color;
        }
    }

    @Override
    public Vehicle clone() {
        return new Car(this);
    }

    @Override
    public boolean isClone(Vehicle target) {
        if (target instanceof Car) {
            Car t = (Car) target;
            return (this.color.equals(t.color) && this.wheels == t.wheels && this.price == t.price);
        }
        return false;
    }
}

Bicycle Class

public class Bicycle extends Vehicle {
    private boolean isCityBike;

    public Bicycle(int wheels, long price, boolean isCityBike) {
        this.wheels = wheels;
        this.price = price;
        this.isCityBike = isCityBike;
    }

    public Bicycle(Bicycle target) {
        super(target);
        if (target != null) {
            this.isCityBike = target.isCityBike;
        }
    }

    @Override
    public Vehicle clone() {
        return new Bicycle(this);
    }

    @Override
    public boolean isClone(Vehicle target) {
        if (target instanceof Bicycle) {
            Bicycle t = (Bicycle) target;
            return (this.isCityBike == t.isCityBike && this.wheels == t.wheels && this.price == t.price);
        }
        return false;
    }
}

Client Usage

public class Client {
    public static void main(String[] args) {
        Car c1 = new Car(4, 30000, "Red");
        Car c2 = (Car) c1.clone();

        System.out.println("Cars are clones: " + c1.isClone(c2));

        Bicycle b1 = new Bicycle(2, 1000, true);
        Bicycle b2 = (Bicycle) b1.clone();

        System.out.println("Bicycles are clones: " + b1.isClone(b2));
        System.out.println("Car and Bicycle are clones: " + b1.isClone(c1));
    }
}

Conclusion

The Prototype Design Pattern offers a flexible and reliable way to clone objects without delving into their internal details. It’s an excellent choice for scenarios where creating a new object instance might be resource-intensive, making cloning a more efficient alternative. Understanding and implementing this pattern can significantly improve code modularity and maintainability.

In this example, we demonstrated how to apply the Prototype Design Pattern in a Java context. By creating clones of Vehicle objects, we showcased how this pattern simplifies object duplication and ensures that the cloned objects maintain the desired functionality.

Happy coding! 🚀