The Basics of Using the Prototype Pattern with PHP 5

The prototype class lets you use many instances of a specific class, without copying objects to different variables. This article, the first of a two-part series, demonstrates the basic functionality provided by this pattern.

Introduction

If you’re a PHP developer who has been building web applications with the object-oriented paradigm for a while, then you’ll have a solid background in how to create classes and define their properties and methods, in addition to handling their instantiation in accordance with the business logic implemented by your PHP scripts.

Now that I mentioned the term "class," surely it’ll be familiar to you that this programming structure is in fact a blueprint. This blueprint is used for all the eventual objects created from it, which logically will expose a behavior consistent with the methods defined by the class in question.

Expressed in simple terms, when you define a class in the context of a given PHP application, what you’re actually doing is creating a prototype model that will be implemented by one or more instances of the originating class. Naturally there will be some variations, particularly if you’re working with subclasses that override and overload methods defined by the respective parent.

However, there’s one thing in particular that I’d like to analyze in detail concerning the definition expressed in the previous sentences. As you may have noticed, I said that it was possible to work with more than one instance of a class, even though this circumstance may happen rather infrequently.

Logically, if this condition ever occurs, it’ll be necessary to build a mechanism that allows one to easily deal with multiple instances of one class, without having to complicate the source code of a certain application with complex, and sometimes inefficient, programming methodologies.

The situation described above is the perfect scenario for implementing the prototype pattern, since it will let you use many instances of a specific class, without copying objects to different variables. At this time you may be wondering how this can be achieved. Well, in plain terms when the prototype pattern is applied, the first instance of a class is used as a prototype model, and all the other instances of the class in question are created by cloning the mentioned prototype object.

Although at first glance the definition of the prototype pattern seems a bit complicated, the truth is that it can be implemented by a few functional PHP code samples very easily. That will be the main goal of this two-part series. More concretely speaking, in this first tutorial of the series I’m going to demonstrate only the basic functionality provided by this pattern, while in the second article I’m going to use the pattern in a more useful situation, that is building an extensible data validation system.

Now that you know the wealth of interesting topics that will be covered in this series, let’s start learning the key concepts of the prototype pattern. Let’s begin this educational journey now!

{mospagebreak title=Implementing the prototype pattern}   

To demonstrate how the prototype pattern works (at least basically for the moment), I’m going to define a bunch of sample classes for establishing the basic structure of different types of data. Then, using these classes, I’ll show you how to create multiple instances of a specific class with the prototype pattern. 

Okay, now that I have explained my plan, please study the signatures of the classes below, which outline the generic structure of a highly-abstracted data entity.

The definitions corresponding to these brand new classes are as follows: 

// define ‘DataPrototype’ class
abstract class DataPrototype{
   private $size;
   private $data;
   abstract public function __clone();
   abstract public function getData();
   abstract public function setData($data);
   abstract public function getSize();
}

// define concrete ‘ArrayPrototype’ class
class ArrayPrototype extends DataPrototype{
   public function setData($data){
     if(!is_array($data)){
       throw new Exception(‘Input data must be an array.’);
     }
     $this->data=$data;
   }
   public function getData(){
     return $this->data;                     
   }
   public function getSize(){
     if(!$size=count($this->data)){
       throw new Exception(‘Error retrieving size of array’);
     }
     return $size;
   }
   public function __clone(){}
}

As shown above, the first sample class has been defined as abstract and its signature is merely an interface for defining the generic behavior of a prototype data entity. Concerning the structure of this base class, you can see that it presents some basic modifiers and accessing methods, which shouldn’t be hard to grasp at all.

On the other hand, the second class, called "ArrayPrototype," is a subclass of the previous "DataPrototype." It naturally implements concretely most of its methods to work specifically with array structures.

So far, so good. At this point I have defined two basic prototype classes, which doesn’t present any major difficulties for the average PHP developer. However, undeniably in this case there’s a characteristic associated with the previous classes that deserves special attention. Please notice how both of them declare the magic "__clone()" method, available with PHP5.

What’s the point of declaring this method? Well, according to the intrinsic definition of the prototype pattern, multiple instances of the same class can be created by cloning a prototype object. Therefore the existence of the method makes sense here, since it will be responsible for cloning objects that might be needed by a concrete application. Sounds pretty logical, right?

All in all, I built a prototype class that defines some straightforward methods for working with arrays. However, I believe that you’ll understand much more easily how the prototype pattern works if I derive another subclass from the base "DataPrototype." In this case, it will be useful for working with files.

Want to learn how this brand new prototype class will be built? Okay, go to the following section and keep reading.

{mospagebreak title=Creating an additional prototype class}

In consonance with the concepts deployed in the previous section, I’d like to complete the demonstration of how the prototype pattern works by defining an additional prototype class. This class will be aimed at working specifically with simple files. Of course, I’m going to create this brand new class by deriving it from the base "DataPrototype" that you learned earlier, meaning that it will also have the magic "__clone()" method, which was included in the other classes as well.

Having explained the basic functionality of this additional prototype class, here is how it looks:

// define concrete ‘FilePrototype’ class
class FilePrototype extends DataPrototype{
   private $file=’default_file.txt';
   public function setData($data){
     if(!is_string($data)){
       throw new Exception(‘Input data must be a string.’);
     }
     $this->data=$data;
     $this->save();
   }
   public function getData(){
     return $this->data;
   }
   public function getSize(){
     if(!$size=filesize($this->file)){
       throw new Exception(‘Error retrieving size of destination
file.’);
     }
     return $size;
   }
   private function save(){
     if(!$fp=fopen($this->file,’w’)){
       throw new Exception(‘Error opening destination
file.’);      
     }
     if(!fwrite($fp,$this->data)){
       throw new Exception(‘Error writing data to destination
file.’);
     }
     fclose($fp);
   }
   public function __clone(){}
}

If you take some time and examine the signature that corresponds to the above "FilePrototype" class, then you’ll see that it implements in a concrete way many of the methods defined by the corresponding parent. In this case, the class performs some useful tasks related to saving and loading strings from a specified text file. 

You should also notice that the previous class declares the magic "__clone()" method, in this way sticking to the structure of the "ArrayPrototype" class that was created in the previous section.

Well, at this stage I think you already grasped the logic that stands behind the prototype pattern, since there are two classes that define the same "__clone()" method. This method is used for creating multiple instances of a specific class, starting from a unique object considered inside the pattern’s context as the prototype.

Logically, as it was discussed in the introduction, the creation of multiple objects is performed by utilizing a cloning procedure. This is a process that certainly deserves a more detailed demonstration. Therefore, in the following section I’m going to set up a short — yet educational — example, which hopefully will show how some objects can be spawned by cloning the aforementioned prototype.  

As you may have guessed, this testing example will be developed in the section to come, so jump ahead and read the next few lines. I’ll be there, waiting for you.

{mospagebreak title=Testing the prototype pattern}

Certainly, I could spend my time and yours explaining theoretically how the prototype pattern works, but I know that you’re expecting to see a concrete example that illustrates how multiple instances of a prototype object can be created during the execution of a specific script.

Therefore, I coded a brief example (shown below), which shows in a friendly fashion how this task is performed via the cloning process that I mentioned previously.

The source code that corresponds to the example in question looks like this:

try{
   // create new ‘ArrayPrototype’ object
   $arrayPrototype=new ArrayPrototype();
   // clone ‘ArrayPrototype’ to create another object 
   $array1=clone $arrayPrototype;
   $array1->setData(array(‘This is element 1′,’This is element
2′,’This is element 3′));
   echo ‘Number of array elements is as following :’.$array1-
>getSize();

   /*
   displays the following
   Number of array elements is as following :3
   */

   $array2= clone $arrayPrototype;
   $array2->setData(array(‘This is element A’,’This is element
B’,’This is element C’,’This is element D’));
   echo ‘Number of array elements is as following :’.$array2-
>getSize();

   /*
   displays the following
   Number of array elements is as following :4
   */

   // create new ‘FilePrototype’ object
   $filePrototype=new FilePrototype();
   // clone ‘FilePrototype’ to create another object
   $file1=clone $filePrototype;
   $file1->setData(‘This string will be saved to file!’);
   echo ‘Size in bytes of destination file is as
following :’.$file1->getSize();

   /*
   displays the following
   Size in bytes of destination file is as following :34
   */
}
catch(Exception $e){
   echo $e->getMessage();
   exit();
}

As you can see, the above code snippet shows in a nutshell how the prototype pattern works, since it uses the built-in PHP "clone()" method to create different instances of a prototype object. More specifically speaking, the first case demonstrates how to spawn two different array objects by cloning their respective prototype, while the second one uses the same approach, but this time with a pair of file-related objects.

Do you grasp the logic followed by the prototype pattern? I bet you do!

Finally, my last suggestion concerning the implementation of this unusual pattern doesn’t differ too much from using other ones: try testing and tweaking all the classes shown here, to give you a more robust background in how this pattern works. I’m sure you’ll have a good time!

Final thoughts

In this first article of the series I walked you though the basics of implementing the prototype pattern with PHP 5. Hopefully, all the hands-on examples coded here will help you expand your existing skills in pattern-based programming.

In the final tutorial of the series, I’m going to demonstrate how to use this handy pattern to develop and expandable data validation application.

You’ve been warned, so don’t miss it!

[gp-comments width="770" linklove="off" ]

chat