Generating Web Pages with the Flyweight Pattern in PHP 5

Unnecessary and balanced instantiation of PHP classes are issues that can be easily solved by using the flyweight design pattern. If you want to learn more about it, you should start reading this article. Welcome to the final part of the series “Using the flyweight pattern with PHP 5.” As you may have guessed, this series walks you through the implementation of this helpful pattern with PHP, and shows you how to apply it in concrete cases.

Introduction

If you’ve been a patient reader and already went through the first part of this series, then you’ll know what the flyweight pattern is about. However, if that’s not the case, let me offer you a quick introduction to it so you can grasp more easily the set of examples that I plan to include in this article.

Essentially, when the flyweight design pattern is applied, there’s one class that controls programmatically the number of objects created across a given application. This implies that the pattern can be used to avoid the unnecessary instantiation of a particular class, and to introduce an improvement in the web server on which the application is running.

Of course, this definition may sound a bit confusing at first, since the implementation of flyweight classes requires some practice. It’s certainly a concept that can be applied to different topics on pattern-based PHP programming as well.

Nonetheless, you shouldn’t feel intimidated by the potential complexity of the subject. In this final part of the series, I’m going to teach you in a step-by-step format how to create in PHP 5 a flyweight class to balance the instantiation of objects that will be used to generate web documents on the fly. Hopefully, by the end of this article, you should have acquired a considerable background in how to apply the flyweight pattern in a real-world situation.

With the preliminaries out of the way, let’s continue learning more about how to create flyweight classes with PHP 5. Let’s go!

{mospagebreak title=Building dynamic web page elements}

Since in the introduction that you just read I stated that I was going to demonstrate how to use the flyweight pattern for building dynamic web pages, my first step is to define a basic class, called “DivElement,” which will be tasked with displaying DIVs on a web document.

Once you have grasped the logic followed by this class, I’ll create a flyweight class which will be responsible for keeping the number of DIV objects limited to a specific number.

But for the moment, pay attention to the signature of the following “DivElement” class, which looks like this:

// define ‘DivElement’ class
class DivElement{
   private $id;
   private $class;
   private $content;
   public function __construct($id=’defaultid’,
$class=’defaultclass’,$content=’Default content for DIV goes
here.’){
     if(!preg_match("/[a-zA-Z]+/",$id)){
       throw new Exception(‘Invalid value for ID property!’);
     }
     if(!preg_match("/[a-zA-Z]+/",$class)){
       throw new Exception(‘Invalid value for name property!’);
     }
     if(!$content){
       throw new Exception(‘Invalid content for div element!’);
     }
     $this->id=$id;
     $this->class=$class;
     $this->content=$content;
   }
   // fetch (X)HTML markup of div element
   public function getHTML(){
     return ‘<div id="’.$this->id.’" class="’.$this-
>class.’">’.$this->content.’</div>’;
   }
}

As you’ll realize, the above “DivElement” class is quite simple to follow. In consonance with the concepts that I deployed a few lines above, it’s tasked with displaying a generic containing DIV on a web document. So far, this isn’t rocket science, right?

Logically, a possible implementation for the previous class, to build a simple web page, could be coded as follows:

// example building a web page using the ‘DivElement’ class
try{
   // instantiate DivElement objects
   $divA=new DivElement(‘diva’,'clsa’,'Content for DIV A goes
here.’);
   $divB=new DivElement(‘divb’,'clsb’,'Content for DIV B goes
here.’);
   $divC=new DivElement(‘divc’,'clsc’,'Content for DIV C goes
here.’);
   // display web page
   echo ‘<html><head><title>Sample Web Page</title></head><body>’.$divA->getHTML().$divB->getHTML
().$divC->getHTML().’</body></html>’;
}
catch(Exception $e){
   echo $e->getMessage();
   exit();
}

As you can see, the prior script shows how to use the “DivElement” class that I defined previously to create a sample web document that contains only three DIVs. The example is very easy to grasp, so you shouldn’t have any problems understanding how it works.

However, the aforementioned “DivElement” class apparently has nothing to do with applying the flyweight pattern. Well, not so fast. Suppose that you want to develop an application that generates dynamic web pages with a few DIV objects, but at the same time, you need to keep the amount of instantiated DIVs limited to a specific number. How can this be done?

Yes, you guessed right! The answer to the above question is obviously using the flyweight pattern. Doing so, it’s feasible to create a web page generator system that not only constructs web documents on the fly, but keeps the number of DIV objects required to build the web pages in question completely under our control.

Therefore, taking into account that the flyweight pattern now starts to play a relevant role, in the course of the section to come, I’m going to show you how to create a flyweight class which will be capable of controlling (and balancing, by the way), the number of instances that correspond to the aforementioned “DivElement” class.

Want to find out how this brand new class will be defined? Visit the next section and keep reading.

{mospagebreak title=Defining a flyweight factory class}

To develop a web page generator system capable of maintaining balance with the number of DIV objects created across the application, I must first define a flyweight class. This class will be provided with the capacity to return only three DIVs to client code, identified as “diva”,”divb”, and “divc” respectively.

Naturally, in accordance with the logic that stands behind the flyweight pattern, this factory class will refuse any attempts to create more DIV objects, in this manner keeping in equilibrium the number of objects used by the web page generator application.

Now that you know how this flyweight class is going to work, I’d like you to pay attention to its signature, which is listed below:

// define ‘FlyweightDivElementFactory’ class
class FlyweightDivElementFactory{
   private $divElements=array();
   public function __construct(){
     $this->divElements['diva']=NULL;
     $this->divElements['divb']=NULL;
     $this->divElements['divc']=NULL;
   }
   // return to calling code only three DIVS
   public function getDivElement($divId){
     if($divId!=’diva’&&$divId!=’divb’&&$divId!=’divc’){
       throw new Exception(‘Invalid ID attribute for DIV
element!’);
     }
     if($this->divElements[$divId]==NULL){
       $this->divElements[$divId]=new DivElement($divId);
     }
     return $this->divElements[$divId];
   }
}

You can see that the above flyweight factory class has one relevant method, called “fetchDivElement(),” which is responsible for controlling the number of DIV objects that will be returned to client code. As one would expect, if an invalid $divID argument is passed to this method, an exception will be triggered, and program’s execution will be stopped.

At this stage, hopefully you’ll have a much better idea of how the previous flyweight factory class does its business. So, provided that my assumption here is correct, it’s time to move forward and see how this class can be put to work to generate dynamic web pages that include only three DIV elements.

The experience sounds interesting, therefore if you wish to learn how the previous flyweight class will be used to create web documents on the fly, please jump into the following section. Don’t worry, since I’ll be there, waiting for you.

{mospagebreak title=Putting the flyweight factory class to work}

As I expressed in the section that you just read, the objective here consists simply of seeing how the previously defined flyweight factory class can be put to work in a useful way. Keeping this in mind, below I created another class, named “WebPageGenerator.” It is tasked with displaying dynamic web pages, in this case by using the functionality provided by the flyweight factory.

Having outlined the behavior for this web page generator class, have a look at its corresponding signature. It is as follows:

// define ‘WebPageGenerator’ class
class WebPageGenerator{
   private $title=’Sample Web Page for Flyweight pattern’;
   public function addDivElement(DivElement $divElement){
     $this->divElements[]=$divElement;
   }
   public function displayWebPage(){
     $html=’<html><head><title>’.$this->title.
‘</title></head><body>’;
     foreach($this->divElements as $div){
       $html.=$div->getHTML();
     }
     $html.=’</body></html>’;
     return $html;
   }
}

If you take some time and examine the signature that corresponds to the above class, then you’ll quickly grasp how it works. In crude terms, this class accepts objects of type “DivElement,” which are used later on to create simple, yet dynamic, web pages.

Nevertheless, I’m pretty certain that you want to see how the aforementioned flyweight factory class fits into this schema. I developed a simple script (displayed below) which shows how to build a web page that only includes three DIV objects.

That being said, please analyze the following example:

// example building a web page using the flyweight design pattern
try{
   // instantiate ‘FlyweightDivElementFactory’ object
   $flyweightDivElemFactory=new FlyweightDivElementFactory();
   // instantiate three DIV elements
   $flyweightDivA=$flyweightDivElemFactory->getDivElement
(‘diva’);
   $flyweightDivB=$flyweightDivElemFactory->getDivElement
(‘divb’);
   $flyweightDivC=$flyweightDivElemFactory->getDivElement
(‘divc’);
   // instantiate ‘WebPageGenerator’ object
$webPageGenerator=new WebPageGenerator();
   // add DIV objects to web page generator
   $webPageGenerator->addDivElement($flyweightDivA);
  
$webPageGenerator->addDivElement($flyweightDivB);
   $webPageGenerator->addDivElement($flyweightDivC);
   echo $webPageGenerator->displayWebPage();
}

catch(Exception $e){
   echo $e->getMessage();
   exit();
}

As you can see, creating web documents using both the flyweight factory and web page generator classes is indeed a very clear process, since the code for the above script is easy to follow.

First, an instance of the flyweight factory class is created to get only the three allowed DIV objects that you learned about in a previous section. Then these DIVs are inputted straight into the web page generator, and finally the pertaining web document is displayed. Quite simple, isn’t it?

However, it’s really interesting to see what happens if I try to create a new DIV, other than those identified as “diva,” “divb” and “divc”. Here is the code that clearly reflects that condition: 

// try instantiating another DIV element (triggers an exception)
// $flyweightDivD=$flyweightDivElemFactory->getDivElement
(‘divd’);

In this case, the flyweight factory class really shows its capacity for keeping the number of DIV objects limited to three.

And finally, here is the corresponding result when I try to instantiate two DIVs that have the same ID attribute:

// instantiate two identical DIV elements
$flyweightDivA=$flyweightDivElemFactory->getDivElement(‘diva’);
$flyweightDivB=$flyweightDivElemFactory->getDivElement(‘diva’);
if($flyweightDivA===$flyweightDivB){
  throw new Exception(‘Div element objects are the same!’);
}

Obviously, two identical objects are returned to calling code, which also triggers an exception.

At this stage, after you have carefully studied all the examples that I wrote here, you should have a decent background in how to create flyweight classes with PHP 5. As in many other cases, the best approach to take here is one of intensive practice, thus I suggest you to spend some time playing with the all the classes that were shown in this article.

Final thoughts

Sad but true, this series has ended. As you learned during this journey, the flyweight design pattern can be useful for controlling the number of class instances created across a given PHP application. In most cases, this approach is followed to improve the performance of a web server that is already overloaded. If this is the situation you are dealing with,  consider using this pattern as part of your PHP applications.

See you in the next PHP tutorial!

Google+ Comments

Google+ Comments