The Singleton and Factory Patterns in PHP: a rendering-capable factory class

In this third part of the series, I will explain how to implement the Factory pattern in conjunction with the polymorphic characteristics of form objects. This will boost the functionality of the factory class by simplifying the process for rendering form elements.

Introduction

Welcome to the third part of the series “The Singleton and Factory Patterns in PHP.” As you probably remember, in the second part of this series, I applied the functionality of the Factory pattern to taking the process of regular form generation from an object-oriented point of view, branching to a different direction from the traditional way for coding web forms.

Essentially, the form generation process can be divided into three key categories: element class definition, form element factory class definition, and finally visual presentation. As you might guess, the first one refers to the stage at which all of the form elements are structured as individual classes, the second implies specifically the definition of the required form factory itself, while the third stage is tasked with rendering each form element according to the specific needs within the program.

So far, I’ve demonstrated a basic implementation of the abstract “formElementFactory” class, which is responsible for creating form element objects, by separating object instantiation from the rest of the application code.

As I mentioned previously in the second part of the series, there are several features that must be added to the logic of the form application, in order to get a more functional version of it, by satisfying several requirements often present in real environments.

Certainly, the first issue to be properly addressed is the rather ineffective implementation of Polymorphism for rendering form elements. The second issue is  the lack of control in the overall presentational layout of the form.

For most of these problems to be efficiently solved, we need to apply some refactoring to the form element factory. We do this by adding the capability to take advantage of the polymorphic features exposed by each form element object, as well as implementing a basic control on the visual presentation for every element.

In this part of the series, I shall provide an overview of the solutions for tackling the above conflicting topics, while maintaining a strong practical approach in the use of design patterns.

So, it’s time to learn more about applying design patterns to object-oriented forms. Let’s get started.

{mospagebreak title=The Factory pattern in a real application: a quick look at the “formElementFactory” class}

As I’ve shown in my previous article, applying the Factory pattern to building object-based forms is fairly simple. As a result, I’ve developed a “formElementFactory” class that creates form objects and allows us to separate object instantiation from the rest of the program.

 To refresh what we’ve learned up to now, let’s have a look at the structure of the “formElementFactory” class and a possible implementation, assuming that each class for building form elements has already been defined. Here is its original definition:

abstract class formElementFactory{
    private function __construct(){}
    public static function createElement($type,$attributes=array()){
        if(!class_exists($type)||!is_array($attributes)){
            throw new Exception(‘Invalid method parameters’);
        }
        // return a new form element object
        return new $type($attributes);
    }
}

As you can see, the above class is fairly simple. The only relevant method that needs to be explained is “createElement()”, which does its work by returning an instance of the corresponding form object, according to the input passed to it. In this way, each time this static method is invoked with the correct parameters, that is the type of form object along with its parameters, a new object is returned for use within the program.

Normally, when the Factory pattern is used, you’ll find similar methods that are tasked with object instantiation, called “create()…” or “factor()..” something. You get the idea. All of them are descriptive names to define a method that performs some kind of object instantiation.

All right, having defined the factory class, a simple implementation looks like this:

$textinput=formElementFactory::createElement(‘textinput’,array
(‘name’=>’fname’,'maxlength’=>’20′));

$passwordinput=formElementFactory::createElement(‘passwordinput’,array
(‘name’=>’password’,'maxlength’=>’20′));

$hiddeninput=formElementFactory::createElement(‘hiddeninput’,array
(‘name’=>’hiddendata’,'value’=>’default’));

$imageinput=formElementFactory::createElement(‘imageinput’,array
(‘name’=>’imgdata’,'src’=>’subimage.gif’));

$fileinput=formElementFactory::createElement(‘fileinput’,array
(‘name’=>’upload’,'value’=>’1′));

Through the above snippet, I’ve created some simple form objects, such as text input boxes, or hidden fields, as a crude implementation for building a form. Once several objects are available, I’m able to display a few form elements by utilizing a regular “foreach” loop, as shown below:

// make array with form element objects
$formElements=array
($textinput,$passwordinput,$hiddeninput,$imageinput,$fileinput);
// display form elements
foreach($formElements as $element){
            echo $element->getHTML().’<br />’;
}

Certainly, the above code shows how simply it is spawning several form objects and getting its (X)HTML code to render the form in a very basic way. As you’ll probably agree, there is not much control over the layout of each element, but the technique presents many advantages compared to writing forms in the usual way. So, returning to the problems that the factory class presents, if I introduce a few modifications within its source code, it’s possible to add form element rendering capabilities to the structure, by taking advantage of the polymorphic nature of each form object.

Perhaps this sounds rather confusing, so let’s jump into the next section to find out how it’s done.

{mospagebreak title=A smarter factory: applying Polymorphism within the “formElementFactory” class}

Essentially, making the form element factory a little “smarter” implies boosting it with the ability to exploit the polymorphic nature of form objects. Since each one of these elements presents the same “getHTML()” method, it’s extremely easy to encapsulate it within the class structure and return the specific (X)HTML code.

Considering this, here is the improved version of the form element factory class:

abstract class formElementFactory{
    private function __construct(){}
    public static function createElement($type,$attributes=array()){
        if(!class_exists($type)||!is_array($attributes)){
            throw new Exception(‘Invalid method parameters’);
        }
        // instantiate a new form element object
        $formElement=new $type($attributes);
        // return form object’s HTML
        return $formElement->getHTML();
    }
}

Quite simple, right? Now, the class is capable of directly returning the (X)HTML code that corresponds to each form object. The overall form generation process is now a little more efficient, reduced to something like this:

// make array with parameters to be passed to the class
$formElements=array(‘textinput’=>array
(‘name’=>’username’,'value’=>”,’maxlength’=>’20′),
‘passwordinput’=>array
(‘name’=>’password’,'value’=>”,’maxlength’=>’20′),
‘submitbutton’=>array
(‘name’=>’name’,'value’=>’Send’));
foreach($formElements as $element=>$attributes){
    // display form elements
    echo formElementFactory::createElement($element,$attributes).’<br />’;
}

Now the code looks stronger and more compact. What I’ve done is simply built a recursive array with the parameters to be passed to the class, in order to display a couple of input fields (a text box and a password field), and a submit button. Finally, the form is roughly displayed, by calling the static “createElement()” method within a “foreach” loop.

To have a better idea of the functionality of the boosted factory class, here is the crude code for displaying several form elements:

// display an input text box
echo formElementFactory::createElement(‘textinput’,array
(‘name’=>’name’,'value’=>”,’maxlength’=>’20′));

// display a password field
echo formElementFactory::createElement(‘passwordinput’,array
(‘name’=>’name’,'value’=>”,’maxlength’=>’20′));

// display a hidden field
echo formElementFactory::createElement(‘hiddeninput’,array
(‘name’=>’name’,'value’=>’default’));

// display a submit image
echo formElementFactory::createElement(‘imageinput’,array
(‘name’=>’name’,'src’=>’submit.gif’));

// display a file upload field
echo formElementFactory::createElement(‘fileinput’,array
(‘name’=>’name’,'value’=>’1′));

// display a radio button
echo formElementFactory::createElement(‘radiobutton’,array
(‘name’=>’name’,'value’=>’1′,’checked’=>’true’));

// display a text area
echo formElementFactory::createElement(‘textarea’,array
(‘name’=>’name’,'value’=>’fill this field’));

// display a check box
echo formElementFactory::createElement(‘checkbox’,array
(‘name’=>’name’,'value’=>’1′,’checked’=>’true’));

// display a button
echo formElementFactory::createElement(‘button’,array
(‘name’=>’name’,'value’=>’button’));

// display a submit button
echo formElementFactory::createElement(‘submitbutton’,array
(‘name’=>’name’,'value’=>’Send’));

// display a reset button
echo formElementFactory::createElement(‘resetbutton’,array
(‘name’=>’name’,'value’=>’Reset’));

// display a select box
echo formElementFactory::createElement(‘selectbox’,array
(‘name’=>’name’,'size’=>’1′,’options’=>array
(’1′=>’value1′,’2′=>’value2′)));

Of course, this is an extremely ineffective implementation of the factory class, but it is useful to have a set of illustrative examples covering how each form element is rendered.

{mospagebreak title=Polishing the Page}

Indeed, I can go one step further by polishing the form’s visual presentation, and define a sample class “Page”, which builds the basic structure of a web page. Doing so, we’re able to combine the functionality of this class along with “formElementFactory”, for a quick and dirty implementation. So, the definition for the simple “Page” class is the following:

class Page {
    private $output;
    public function __construct(){
        $this->output=’<html><head><title>Default
Page</title></head><body><h1>Default Page</h1></body></html>’;
    }
    public function makeHeader($header){
        $this->output=$header;
    }
    public function makeBody($body){
        $this->output.=$body;
    }
    public function makeFooter($footer){
        $this->output.=$footer;
    }
    public function getPage(){
      return $this->output;
    }
}

In simple terms, the above class presents the classic methods for building the header, body and footer sections of a web page, while its constructor sets up a default sample page. Definitely, I won’t stop explaining its logic. Instead, I’ll show an example that uses this class to generate a login form. Here is the sample code:

// instantiate a new Page object
$page=new Page();

// build header page section
$page->makeHeader(‘<html><head><title>Object-Based web
form</title></head><body>’);

// add form tag and build a table header
$body=’<form action=’.$_SERVER['PHP_SELF'].’
method=”post”><table><tr><td>Object-Based web form</td></tr>’;

// build a text input box
$body.=’<tr><td>User ID ‘.formElementFactory::createElement
(‘textinput’,array(‘name’=>’userid’,'maxlength’=>’20′)).’</td></tr>’;

// build a password field
$body.=’<tr><td>Password ‘.formElementFactory::createElement
(‘passwordinput’,array(‘name’=>’passwrd’,'maxlength’=>’20′)).
‘</td></tr>’;

// build a submit button
$body.=’<tr><td>’.formElementFactory::createElement
(‘submitbutton’,array
(‘name’=>’send’,'value’=>’Log in’)).’</td></tr>’;
$body.=’</table></form>’;

// add the code to the body section
$page->makeBody($body);

// build the footer page section
$page->makeFooter(‘</body></html>’);

// display the page
echo $page->getPage();

The above code uses the “Page” class to generate the structure of a web page, by displaying the header, body, and footer parts. Notice the rough usage of the “formElementFactory” class to obtain the code for the required form elements, by decoupling object instantiation from the general form rendering process.

The only point worth mentioning on the above example is the extensive use of the static “createElement()” method, which is naturally invoked without the need to explicitly instantiate an object from the form element factory class. As you remember, this class has been declared as abstract, therefore any attempt to instantiate an object from it will result in the PHP interpreter triggering a fatal error.

Despite the fact that I’ve hidden behind the structure of the factory class all of the required processing for displaying form elements, I’m still far away from having an efficient rendering mechanism. Notice that the rough use of the “Page” class is merely an example, not suitable for use in a fully functional application.

However, the factory class works quite well, by implementing the Factory pattern, for solving annoying tasks involved in displaying programmatically web form elements. Now, I’ve exposed a common problem that comes up when building real-world applications that can be addressed in an effective way, in this case by applying a design pattern.

Wrapping up

That’s all about it for now. In this third part of the series, I’ve explained how to implement the Factory pattern in conjunction with the polymorphic characteristics of form objects to boost the functionality of the factory class, by simplifying the process for rendering form elements.

Now, let’s pay attention to the next part of the series, where I’ll explain the correct application of the Singleton pattern, in order to work with only a single instance of a form factory class. As you’ll see in short, making a class a Singleton is quite easy to do, allowing you to write robust PHP4 programs, by reducing the hassles related to manipulating multiple object instances.

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan