PHP Prototype Design Pattern Part I: How to Clone

cloneClone My Instance

The Prototype Design Pattern is a creational one that I’ve been warming up to lately. Basically, the purpose of the Prototype pattern is to reduce the cost of instantiating objects through the use of cloning. So, the first thing we need to do is to understand how to use cloning in PHP and what it does.

Fortunately, PHP has a __clone() function built right into it, and it makes creating a Prototype design pattern a lot easier than languages where you have to write your own clone function. So, this post will just look at how the __clone() function works and how it saves resources in programming.

Before we get going, go ahead and play the example (and meet the lovely Ada Lovelace) and download the source code:
PlayDownload
Take a look at the listings, and you’ll see where the __clone() function is located. Also, see how it is used to create a cloned instance.

A Class with a Clone Within

To clone an object in PHP, you need to create the Class you plan to clone with the __clone() function inside. So for ClassA to be cloned by $objectB, I need to include the __clone function inside ClassA. The instantiation process would look like the following:

$objectA = new ClassA();
$objectB = clone $objectA;

To get started, then, we’ll need to create a class that contains a __clone() function. This will be an abstract class, and the __clone() function will be abstract as well.

<?php
//CloneMachine.php
abstract class CloneMachine
{
	protected $designation;
 
	public function showHelp($designate)
	{
		$this->designation=$designate;
 
		echo "<img src='ada.png'>";
		echo "<br />$this->designation <p />";
	}
	abstract function __clone();
}
?>


That’s a pretty busy abstract class, and the child classes are going to have to implement the __clone() function. The showHelp() function displays a PNG file showing Ada Lovelace (or Ada Countess of Lovelace for the royals among you), and then it displays a message through the $designation property. Ada who? Since you asked….

As we all know Charles Babbage was the father of the digital computer, with his difference engine and later the Analytical Engine. While developing the Analytical Engine, he corresponded with Ada Lovelace, who was quite a mathematician in her own right. She assisted Babbage on working out an algorithm for calculating a sequence of Bernoulli numbers. It has been debated how much she actually did on developing the algorithm, but there is no doubt that she found an error in the algorithm and corrected it. Hence, she is the first debugger, if not the first programmer.

Lately I’ve been very busy with everything from an edX course at MIT to the Propagate course with the Boston PHP group–not to mention my day job at the university. So when thinking of a clone, I’d really like some help from someone like Ada. Hence, I needed an agency I could contact to get help. The following class is that agency:

<?php
//Agency.php
include_once('CloneMachine.php');
class Agency extends CloneMachine
{
	function __construct()
	{
		echo "This message only appears in the original!<br />";
	}
	function __clone() {}
}
?>

As you can see, there is not a lot to the Agency class, and the constructor function is required only to make a point. The main feature of the class that is crucial is the implemented __clone() function. The pair of curly braces is actually all I need to implement it, and that’s all there is. (In fact, I could take out the constructor function, and it would work just fine.)

To see what’s going on, the Client class shows how the clone is actually created:

<?php
include_once('Agency.php');
class Client
{
	public function __construct()
	{
		$debugger= new Agency();
		$debugger->showHelp("Meet the Original Debugger");
 
		$moreHelp= clone $debugger;
		$moreHelp->showHelp("A cloned debugger!");
	}
}
$client=new Client();
?>

As you saw when you ran the program, the message from the Agency class constructor appears at the very top:

This message only appears in the original!

That’s because when you instantiate an instance, the constructor fires. However, when you clone an object, the constructor function does not launch. That’s how cloning saves resources. It doesn’t launch the constructor function every time an instance is created using a clone method.

On to the Prototype

In Chapter 6 of Learning PHP Design Patterns, I discussed this in more detail, including why you should not do too much with the constructor. For now, though, understand how to use the PHP __clone() function and that clones save resources by not launching an object’s constructor function. In Part II of the Prototype Design Pattern, you will see the role played by the __clone() function.

Share

Copyright © 2013 William Sanders. All Rights Reserved.

2 Responses to “PHP Prototype Design Pattern Part I: How to Clone”


Leave a Reply