AlgoMaster Logo

Prototype Design Pattern

Ashish

Ashish Pratap Singh

6 min read

The Prototype Design Pattern is a creational design pattern that lets you create new objects by cloning existing ones, instead of instantiating them from scratch.

It’s particularly useful in situations where:

  • Creating a new object is expensivetime-consuming, or resource-intensive.
  • You want to avoid duplicating complex initialization logic.
  • You need many similar objects with only slight differences.

The Prototype Pattern allows you to create new instances by cloning a pre-configured prototype object, ensuring consistency while reducing boilerplate and complexity.

The Challenge of Cloning Objects

Imagine you have an object in your system, and you want to create an exact copy of it. How would you do it?

Your first instinct might be to:

  1. Create a new object of the same class.
  2. Manually copy each field from the original object to the new one.

Simple enough, right?

Well, not quite.

Problem 1: Encapsulation Gets in the Way

This approach assumes that all fields of the object are publicly accessible. But in a well-designed system, many fields are private and hidden behind encapsulation. That means your cloning logic can’t access them directly.

Unless you break encapsulation (which defeats the purpose of object-oriented design), you can’t reliably copy the object this way.

Problem 2: Class-Level Dependency

Even if you could access all the fields, you'd still need to know the concrete class of the object to instantiate a copy.

This tightly couples your cloning logic to the object's class, which introduces problems:

  • It violates the Open/Closed Principle.
  • It reduces flexibility if the object's implementation changes.
  • It becomes harder to scale when you work with polymorphism.

Problem 3: Interface-Only Contexts

In many cases, your code doesn’t work with concrete classes at all—it works with interfaces.

For example:

Here, you know the object implements a certain interface (Shape), but you don’t know what class it is, let alone how to create a new instance of it. You’re stuck unless the object knows how to clone itself.

The Better Way: Let the Object Clone Itself

This is where the Prototype Design Pattern comes in.

Instead of having external code copy or recreate the object, the object itself knows how to create its clone. It exposes a clone() or copy() method that returns a new instance with the same data.

This:

  • Preserves encapsulation
  • Eliminates the need to know the concrete class
  • Makes the system more flexible and extensible

Let’s walk through a real-world example to see how we can apply the Prototype Pattern to build a more efficient and maintainable object creation workflow.

The Problem: Spawning Enemies in a Game

Let’s say you’re developing a 2D shooting game where enemies appear frequently throughout the gameplay.

You have several enemy types with distinct attributes:

  • BasicEnemy: Low health, slow speed — used in early levels.
  • ArmoredEnemy: High health, medium speed — harder to defeat, appears later.
  • FlyingEnemy: Medium health, fast speed — harder to hit, used for surprise attacks.

Each enemy type comes with predefined properties such as:

  • Health (how much damage they can take)
  • Speed (how quickly they move across the screen)
  • Armor (whether they take reduced damage)
  • Weapon type (e.g., laser, cannon, missile)
  • Sprite or appearance (the visual representation)

Now, imagine you need to spawn a FlyingEnemy. You might write code like this:

And you’ll do the same for dozens, maybe hundreds, of similar enemies during the game.

But Here’s the Problem

  • Repetitive Code: You’re duplicating the same instantiation logic again and again.
  • Scattered Defaults: If the default speed or weapon of FlyingEnemy changes, you need to update it in every single place you created one.
  • Error-Prone: Forget to set one property? Use a wrong value? Bugs will creep in silently.
  • Cluttered Codebase: Your main game loop or spawn logic becomes bloated with object construction details.

As your game scales — adding more enemy types, behaviors, or configurations — this naive approach quickly becomes hard to manage and maintain.

You need a clean, centralized, and reusable way to create enemy instances with consistent defaults while allowing minor tweaks.

To avoid repetitive instantiation and duplicated setup logic, we turn to the Prototype Design Pattern.

The Prototype Design Pattern

The Prototype pattern specifies the kinds of objects to create using a prototypical instance and creates new objects by copying (cloning) this prototype.

Instead of configuring every new object line-by-line, we define a pre-configured prototype and simply clone it whenever we need a new instance.

Class Diagram

Here’s how it works:

  • Define a Prototype InterfaceThis declares the clone() method, which every cloneable object must implement.
  • Implement Concrete PrototypesEach object that needs to be cloneable (e.g., FlyingEnemyArmoredEnemy) implements the Prototype interface and provides logic to clone itself.
  • Client Requests a CloneWhen a client needs a new object (e.g., enemy), it doesn’t new it directly — it simply asks the prototype object to copy itself.

Optional Enhancement: Prototype Registry

As your system grows with more enemy types or components, you can introduce a Prototype Registry:

  • It stores a collection of named prototypes (e.g., "flying""armored").
  • Clients request a clone of a named prototype using a simple key.
  • This separates the concern of what to create from how to configure it.

Implementing Prototype

Let’s refactor our enemy spawning system in a game using this pattern.

We’ll break the implementation down into 4 clear steps:

Step 1: Define the Prototype Interface (EnemyPrototype)

This interface declares a clone() method, which every cloneable enemy type must implement.

Step 2: Create the Concrete Prototype Class (Enemy)

This is the actual class that we want to clone. It implements the EnemyPrototype interface and defines the cloning behavior using a copy constructor, which is a clear and reliable way to clone objects in Java.

A Quick Note on Cloning:

  • Shallow Copy: This implementation performs a shallow copy. It’s fine if all fields are primitives or immutable (like String). But if Enemy had a field like a List, both the original and cloned enemies would share the same list object, which can cause subtle bugs.
  • Deep Copy: If your object contains mutable reference types, you should create a deep copy in the copy constructor. For example:

Java’s built-in Object.clone() is often avoided due to its limitations and shallow behavior. Manual cloning using copy constructors or builders is more flexible and safer.

Step 3 (Optional): Create a Prototype Registry (EnemyRegistry)

Prototype Registry (or Manager) stores pre-configured prototype instances. This keeps your code organized, especially when you have many types of enemies.

Now your game logic can fetch enemies by type without worrying about how they’re constructed.

Step 4: Using the Registry in Your Game

Here’s how everything comes together in the main game loop or enemy spawner logic:

Output