Use the Prototype Pattern in PHP | Learn Design Patterns in 2023

Prototype Pattern in PHP

The prototype pattern in PHP is a creational design pattern that uses existing objects to create its clones. The pattern is helpful when the application frequently needs to copy existing complex objects. The pattern delegates the replication to the objects.

 The application polymorphically calls the clone() method on the objects, and that’s one upside of this design it doesn’t couple the client code with concrete classes. Here’s the complete architecture of the feature you’ll implement in the rest of the article.

Prototype Pattern in PHP
Prototype Pattern in PHP

Not sure what’s going on? Stay tuned because, by the end of the article, you will be better off with the prototype design pattern in PHP.

Definition | Builder Design Pattern in PHP

“The prototype is a creation design pattern that uses existing objects to create its clones.”

Prototype Pattern in PHP
Prototype Design Pattern

This design pattern delegates the cloning responsibility to the prototype objects. It lets the client code polymorphically clone the objects of the same parent class or interface.

Drag’n’Drop | A Real World Example of Prototype Pattern in PHP

Your company has made a drag and drog low-code UI application. Users can build UI interfaces using drag-and-drop features. You are assigned to implement a sub-feature to help replicate/clone existing UI elements. This feature will help create consistent UIs and themes.

Drag and Drop UI Elements
Drag and Drop UI Elements

So, How do you go about this problem?

A UI element could have many properties. Copying a UI element in your application means copying the instance of the particular UI element. That instance could have these properties and methods, some more specific to the type of UI element. So, copying such an object could be a challenge.

The approach that may pop up in your mind immediately is manually copying through the object’s attributes and methods and then pasting it to a new object of the same class. That may sound right, but there are some facts that you should be well aware of.

So, What’s Wrong with this Implementation?

Private object data & added dependency

An object could have private fields and methods that only the object itself can access. Though you can copy over the accessible field, how about the private ones? That’s definitely a miss, and that’s not exactly what we want to do. 

On top of that, your client code depends on the concrete classes and their respective implementations. That makes your code less flexible and maintainable because you may have to change the client code on any change that follows.

Code duplication

Objects of the same classes have a lot in common. Trying to cover the differences will force you to duplicate similar parts in your code. For instance, every shape has coordinates (x, y), but a circle has a radius, and a rectangle has sides. So, a concrete implementation for these shapes will have a recurring logic for cloning the coordinates.

Code duplication is undoubtedly a bad thing to have in your application. It makes the change process difficult and error-prone.

Open-Closed Principle

The open-closed principle states, “A class should be open to extension and closed to modification.” and the current approach violates this principle. How? Suppose you have a change to a concrete object in terms of data or implementations. Then the existing cloning logic may be good for nothing because the change affected it somehow.

Next, you would modify the existing cloning code, which is precisely what this principle forbids.

Liskov Substitution Principle

Liskov Substitution principle states that “An object of a superclass shall be replaceable with objects of its subclasses.” In other words, the objects should be interchangeable. Now, if your code depends on concrete implementations, then there’s a chance that you are violating this principle.

To have this sort of interchangeability, you should be programming to interfaces than the concrete sub-classes.

Introducing Prototypes

A Prototype is an object that can clone itself. You can have a bunch of prototype objects that you can use to create as many clones as you need. But how does it support cloning? It does so by implementing a clone() method.

Prototype class
Prototype class

The prototype design pattern is based on delegating the cloning process to the object. Usually, there is either an interface or an abstract class with a clone method. Either way that the sub-classes have to implement the clone method.

What are the benefits of this design?

  • Your client code doesn’t depend on the concrete classes anymore. It can call the clone method polymorphically.
  • An object can copy private fields to the clones, which is otherwise not doable outside the class.
  • A more flexible design allows you to add sub-classes without breaking the application code because your application only sees the interface.
  • The sub-classes with a common parent class can implement the clone method distinctly, and the client code will not be concerned with these concrete implementations.
  • It is easier to clone an object than to create a new one from scratch with the same configurations.

What is a Prototype Registry Class?

A Prototype Registry class is an extension of the prototype design pattern, similar to a cache. A Registry class uses a hashmap to store prototypes. So, it is always convenient to create the prototypes once and store them in the registry. The next time you need to access a prototype, you can reach out to the registry rather than create it from scratch.

Prototype Registry Class
Prototype Registry Class

A cache, by design, has faster access time but is non-persistent, meaning that these prototypes will exist in memory during your application’s runtime. However, you can add a persistence layer serializing the prototypes to permanent storage like a database or a file. But that’s out of the scope of this article.

Complete Architecture | Prototype Design Pattern in PHP

Prototype Design Pattern in PHP

The following example creates the cloning feature using the prototype pattern in PHP.

Code | Prototype Design Pattern in PHP

<?php
abstract class UIElement {
    private $width;
    private $height;
    private $backgroudColor;
    private $text;
 
    function getWidth() {
        return $this->width;
    }
 
    function getHeight() {
        return $this->height;
    }
 
    function getBackgroundcolor() {
        return $this->backgroundColor;
    }
 
    function getText() {
        return $this->text;
    }
 
    function setText($text) {
        $this->text = $text;
    }
 
    function setWidth($width) {
        $this->width = $width;
    }
 
    function setHeight($height) {
        $this->height = $height;
    }
 
    function setBackgroundcolor($color) {
        $this->backgroundColor = $color;
    }
 
    function render() {
        $width  = $this->getWidth();
        $height = $this->getHeight();
        $text   = $this->getText();
        $background = $this->getBackgroundcolor();
 
        return 'Width: '.$width.' '.'Height: '.$height.' '.' Text: '.$text.' '.'Background: '.$background.PHP_EOL;
    }
 
    abstract function clone();
}
 
class Label extends UIElement {
 
    function render() {
        $features = parent::render();
        return 'The label has '.$features;
    }
 
    function clone() {
        return clone $this;
    }
}
 
class Button extends UIElement {
 
    function render() {
        $features = parent::render();
        return 'The button has '.$features;
    }
 
    function clone() {
        return clone $this;
    }
}
 
function main() {
 
    //Creating the button prototype
    $buttonPrototype = new Button();
    $buttonPrototype->setWidth('8px');
    $buttonPrototype->setHeight('4px');
    $buttonPrototype->setBackgroundcolor('White');
    $buttonPrototype->setText('FuelingPHP Button');
 
    //Creating the label prototype
    $labelPrototype = new Label();
    $labelPrototype->setWidth('4px');
    $labelPrototype->setHeight('2px');
    $labelPrototype->setBackgroundcolor('White');
    $labelPrototype->setText('FuelingPHP Label');
 
 
    $buttonClone = $buttonPrototype->clone();
    $labelClone  = $labelPrototype->clone();
 
    echo $buttonClone->render();
    echo $labelClone->render();
}
 
main();
 
 
?>

Output | Builder Design Pattern in PHP

The button has Width: 8px Height: 4px  Text: FuelingPHP Button Background: White
The label has Width: 4px Height: 2px  Text: FuelingPHP Label Background: White

Pros and Cons of the Prototype Pattern in PHP

ProsCons
Satisfied Open-closed and Liskov Substitution principles.Maybe redundant now because many modern programming languages have a clone method for objects.
You can create a clone polymorphically without depending on concrete classes.Objects with circular references can be tricker to clone.
You can easily clone a concrete object rather than create it from scratch.
You can have countless pre-configured objects, and your application can clone them on the fly.
The prototype Registry class can add a feature of fast in-memory access with methods for quick prototype search.

Where is the Prototype Pattern Used?

  • When you want to create a complex object from a base object without repeating the building process from scratch.
  • When you want to reduce recurring sub-classes that differ in configurations only. You can instead create the prototypes and clone them on the fly.
  •  When you don’t want your client code to depend on objects of concrete classes for cloning.

Frequently Asked Questions

What type of design pattern is the prototype?

The prototype is a creation design pattern that uses existing objects to create its clones. The pattern is helpful when the application frequently needs to copy existing complex objects.

What is the prototype registry class?

The prototype registry class acts as a cache for prototype objects. It stores these objects in memory and provides them when a client needs to use them for cloning.

Is a prototype registry class necessary?

No, it is an added feature. You can extend the prototype pattern if you have lots of prototypes. The registry class provides a hashmap for storage and exposes methods to search for the relevant prototype objects. 

Using the Prototype Pattern in PHP Today

Voila! That’s all about the prototype patterns in PHP. As a throwback, let’s see what we have seen thus far. The need for the design came when we were trying to clone complex objects and UI elements manually. The article explains why it is not a good idea to copy an object that way.

So, the article then uses a prototype object which is the central theme of this pattern. A prototype object implements a clone() method and calls it to replicate. That’s useful when we want the client code to depend on abstractions rather than concrete classes and implementations.

With the prototype pattern, the client code can call clone() on the objects without worrying about their concrete classes or implementations as long as they follow a common interface or extend from a common parent class.

So, that’s all about it. We hope you are now well aware of this design pattern and can implement it whenever possible.

See you in another design pattern article. Stay tuned at FuelingPHP.

Books on Design Patterns

Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.

Design Patterns: Elements of Reusable Object-Oriented Software

Design Patterns: Elements of Reusable Object-Oriented Software book

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.

Check it out on amazon

Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.

Check it out on amazon

Design Patterns in PHP Learning Series.

This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.


Article Categories

Article Tags

© 2023 Confident.Systems