In the previous article, we learned about the design pattern called The Builder Pattern. In this article, let’s learn about a new creation design pattern called The Prototype Pattern.

What is the Prototype Pattern?

Prototype Pattern is a creation design pattern. In essence, this kind of design pattern provides a mechanism for creating an object by copying from an existing object instead of using the new keyword. The new object is a copy that can be completely identical or has been changed some properties compared to the original object, we can freely change the data of this copy object without affecting the original statue. The Prototype Pattern is mostly used when you don’t want to spend a lot of time and effort on creating a completely new object while you already have another similar object that exists.

Prototype Pattern is a ceational design pattern
Source: refactoring.guru

Structure

The structure of the Prototype Pattern consists of 3 important components: Prototype, Concrete Prototype, and Client.

Structure of Prototype Pattern
Source: refactoring.guru
  • The Prototype interface declares the cloning methods. In most cases, it’s a single clone method.
  • The Concrete Prototype class implements the cloning method. In addition to copying the original object’s data to the clone, this method may also handle some edge cases of the cloning process related to cloning linked objects, untangling recursive dependencies, etc.
  • The Client can produce a copy of any object that follows the prototype interface.

When to Use the Prototype Pattern?

Here are some cases you should consider using the Prototype Pattern for your code:

  • You want to reduce the number of sub-classes that only differ in the way they initialize their respective objects.
  • You want your code not to depend on the concrete classes of objects that you need to copy.
  • The cost of creating new objects using the new operator is considerable.

clone and __clone() in PHP

PHP provides the clone keyword that allows cloning an existing object without having to initialize a new one.

Syntax:

$object2 = clone $object1;

In addition to the clone keyword, PHP also provides the __clone() magic method. As soon as the object is fully cloned, the __clone() method of this newly created object will be invoked.

Example:

<?php
class Person {
    public $name = "John Smith";
    public $age = 21;
    public $occupation = "Software Developer";

    public function __clone() {
        echo "__clone() is invoked!";
    }
}

$person1 = new Person();
$person2 = clone $person1;
echo $person2->name . " is " . $person2->age . " years old and he is a " . $person2->occupation;
?>
Output:
__clone() is invoked!
John Smith is 21 years old and he is a Software Developer;

Example of the Prototype Pattern

<?php
abstract class BookPrototype {
    protected $title;
    protected $topic;

    abstract function __clone();

    function getTitle() {
        return $this->title;
    }

    function setTitle($titleIn) {
        $this->title = $titleIn;
    }

    function getTopic() {
        return $this->topic;
    }
}

class PHPBookPrototype extends BookPrototype {
    function __construct() {
        $this->topic = "PHP";
    }

    function __clone() {
    }
}

class SQLBookPrototype extends BookPrototype {
    function __construct() {
        $this->topic = "SQL";
    }

    function __clone() {
    }
}

class HTMLBookPrototype extends BookPrototype {
    function __construct() {
        $this->topic = "HTML";
    }

    function __clone() {
    }
}
// Client
echo "BEGIN TESTING PROTOTYPE PATTERN\n\n";

$phpProto = new PHPBookPrototype();
$sqlProto = new SQLBookPrototype();
$htmlProto = new HTMLBookPrototype();

$book1 = clone $sqlProto;
$book1->setTitle("SQL for Cats");

echo "Book 1 topic: " . $book1->getTopic() . "\n";
echo "Book 1 title: " . $book1->getTitle() . "\n\n";

$book2 = clone $phpProto;
$book2->setTitle("Learning PHP from Scratch");

echo "Book 2 topic: " . $book2->getTopic() . "\n";
echo "Book 2 title: " . $book2->getTitle() . "\n\n";

$book3 = clone $sqlProto;
$book3->setTitle("Learning SQL from Scratch");

echo "Book 3 topic: " . $book3->getTopic() . "\n";
echo "Book 3 title: " . $book3->getTitle() . "\n\n";

$book4 = clone $htmlProto;
$book4->setTitle("Learning HTML from Scratch");

echo "Book 4 topic: " . $book4->getTopic() . "\n";
echo "Book 4 title: " . $book4->getTitle() . "\n\n";

echo "END TESTING PROTOTYPE PATTERN";
?>

Output:

BEGIN TESTING PROTOTYPE PATTERN
Book 1 topic: SQL
Book 1 title: SQL For Cats

Book 2 topic: PHP
Book 2 title: Learning PHP from Scratch

Book 3 topic: SQL
Book 3 title: Learning HTML from Scratch

Book 4 topic: HTML
Book 4 title: Learning HTML from Scratch

END TESTING PROTOTYPE PATTERN

The Pros and Cons of the Prototype Pattern

Pros

  • The Prototype Pattern helps reduce costs, time and contributes to increase the performance of the program by not using the new operator to create new objects.
  • It helps reduce complexity for object initialization: because each class only implements its own way of cloning.
  • We can also avoid classifying and creating multiple sub-classes to initialize objects such as the Abstract Factory Pattern.
  • It helps you increase the flexibility of the system because it allows creating new objects by changing some properties of the original object that it copied.

Cons

  • Cloning complex objects that have circular references might be very tricky.

Conclusion

In this article, we have learned a lot about the Prototype Pattern. I hope that this design pattern will be a perfect solution to one of your software development problems sometime in the future.

In the next article of this series, we will learn about another creation design pattern called the Singleton Pattern. Stay tuned!

For further reading:

  1. https://refactoring.guru/design-patterns/prototype
  2. https://sourcemaking.com/design_patterns/prototype/php

Leave a Reply