The Singleton and Factory Patterns in PHP: designing an object factory

This article, the second part of a series, is focused on implementing the Factor Pattern by designing a form element factory.

Introduction

This is the second part of the series “The Singleton and Factory Design Patterns in the real world.” Welcome back. Throughout the first part of the series, I provided you with an overview of building object-oriented forms using two popular design patterns: the Singleton and the Factory patterns.

At this point, I assume that these aren’t foreign concepts to you, since they were reviewed in the first part. Just in case  you don’t feel very seasoned with patterns, you should start by reading my previous article, where I offered a friendly introduction to them.

If you’re used to writing a lot of repetitive code to build your web forms, probably you’ve found the technique that I previously explained to create forms, based on an object-oriented approach, quite interesting. Due to the advantages inherent in this method, form generation can be translated into a flexible and straightforward process that strongly encourages code re-use.

Focusing again on the objective of this series, this second part is aimed specifically at implementing the Factory Pattern, by designing a form element factory, which will be tasked with building regular form components, in this way abstracting the rendering process for each element.

Essentially, the article is intended to provide a practical step-by-step guide to apply design patterns in real world conditions, such as form design an implementation, by attending the requirements that most developers must face on a frequent basis.

Thus, it’s time to go deeper into the object-oriented form generation method. Let’s go!

{mospagebreak title=The first step within the development process: coding form element classes}

A natural place to start building a form element factory is by coding the required classes to render each element. Maybe this sounds like common sense, but in fact it’s a logical starting point within the development process. As you’d expect, writing the code for each form element doesn’t present major difficulties due to its simplicity, but since we’re dealing with many components, the task will be rather long.

A brief disclaimer is needed here: it’s often a better solution to define a base class that contains the methods and properties shared by any form element, and then derive the required specific subclasses. However, in this case I won’t stick to this method, simply to make the code a little more abbreviated and demonstrate the polymorphism of objects. Anyway, by the end of this series you’ll have the knowledge to implement your own version of the form application.

Having said that, let’s list the class source code for each form element. The first class renders a text input box, and looks like this:

// class textinput
class textinput{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of attributes’);
    }
    $this->html=’<input type=”text” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

As I explained in the previous article, the above class generates the (X)HTML markup to display a regular input text box, which is returned by the “getHTML()” method. Let’s move on to listing the class responsible for building password fields:

// class passwordinput
class passwordinput{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of attributes’);
    }
    $this->html=’<input type=”password” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

Next, here is the list for hidden fields, file upload elements and submit images:

// class hiddeninput
class hiddeninput{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”hidden” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class fileinput
class fileinput{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”file” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class imageinput
class imageinput{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of attributes’);
    }
    $this->html=’<input type=”image” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

Okay, sit tight just a little longer and jump into the next few lines. As you might guess, I’ll show the remaining classes to get the form element classes completed.

{mospagebreak title=Finishing the round: listing the rest of form element classes}

Now that you have the code for input text boxes, hidden fields, file input fields and so forth, I’ll finish writing the rest of the form element classes, that is, radio buttons, checkboxes, select boxes and text area fields, to name a few.

Notice that most of element classes are similar in their source code. This might lead you to think that all of the classes can be unified into one generic class that would accept one parameter (the element’s name), and accordingly return the corresponding (X)HTML code.

While this method might be valid for reducing the length of code, it’s preferable to keep each form element class as a separate entity within the application, allowing you to maintain a greater level of flexibility.

Now, it’s time to finish the coding round by listing the classes for the rest of the form elements. Here is the code for radio buttons, checkboxes, and buttons:

// class radiobutton
class radiobutton{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”radio” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class checkbox
class checkbox{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”checkbox” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class button
class button{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”button” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

Finally, below are the classes for rendering submit buttons, reset buttons, text areas and select boxes:

// class submitbutton
class submitbutton{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”submit” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class resetbutton
class resetbutton{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<input type=”reset” ‘;
    foreach($attributes as $attribute=>$value){
      $this->html.=$attribute.’=”‘.$value.’” ‘;
    }
    $this->html.=’/>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class textarea
class textarea{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<textarea ‘;
    $textvalue=”;
    foreach($attributes as $attribute=>$value){
      ($attribute!=’value’)?$this->html.=$attribute.’=”‘.$value.’”‘:$textvalue=$value;
    }
    $this->html=preg_replace(“/”? $/”,”">”,$this-
>html);
    $this->html.=$textvalue.’</textarea>’;
  }
  public function getHTML(){
    return $this->html;
  }
}

// class selectbox
class selectbox{
  private $html;
  public function __construct($attributes=array()){
    if(count($attributes)<1){
      throw new Exception (‘Invalid number of
attributes’);
    }
    $this->html=’<select ‘;
    $options=”;
    foreach($attributes as $attribute=>$value){
      if($attribute!=’options’){
        $this->html.=$attribute.’=”‘.$value.’” ‘;
      }
      else{
        foreach($value as $values=>$label){
          $options.=’<option value=”‘.$values.’”>’.$label.’</option>’;
        }
      }
    }
    $this->html=preg_replace(“/”? $/”,”">”,$this-
>html);
    $this->html.=$options.’</select>’; 
  }
  public function getHTML(){
    return $this->html;
  }
}

By this point, most of the hard work has been done. Now that you have all of the form element classes defined, I can go one step further and start writing the form element factory. Thus, click below and keep reading.

{mospagebreak title=The Factory Pattern in action: developing the “formElementFactory” class}

In general terms, the Factory pattern allows you to separate object instantiation from the rest of the client code. The immediate benefit of applying this pattern is that you’re able to create an instance of a class within a program that returns a specific object, each time it’s invoked with the proper parameters (called input), without being concerned about how the object is instantiated. Object instantiation is handled internally by the class, which is called a “factory,” while the object instantiated is the “product.”

Now, allow me to explain how I translate the above theory into a functional class. First, I’ll define a simple abstract class, called “formElementFactory,” which returns an instance of a form element object, according to the input passed to it. To clarify things, here is the first definition for this 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’);
    }
    // return a new form element object
    return new $type($attributes);
  }
}

As you can see, the class is not complex. I’ve defined only two methods: the empty private constructor and the public static “createElement()” method. Certainly, this method takes care of the proper object instantiation and accepts two parameters: $type and the $attributes array. The first one represents the type of object to be instantiated, while the second means its attributes.

The line below:

return new $type($attributes);

carries out the object instantiation. Simple and powerful, eh?

Also, the class expects the input to conform to a specific type of object. I could go even further in terms of abstraction by refactoring the class, so it can accept an object with no explicit type. In that case, I’d be applying the Abstract Factory pattern, which at the moment is out of the scope of the article.

By this point, I hope that you’re wondering why I declared the class as abstract. The reason is simple. An abstract class cannot be instantiated, thus any attempt to do so will result in a fatal error. Declaring the class abstract is an efficient way to use its methods without dealing with its instantiation. This means that there’s no class instance, but the methods are accessible from outside its context.

PHP5 makes it really easy to work with abstract classes. Unfortunately PHP4 doesn’t support them, but there is a workaround to emulate this structure, generally by coding a “die()” statement within the constructor.

The rest of the code speaks for itself. Parameter validation is performed at a basic level by checking whether the type of object exists, as well as whether the $attributes variable is an array. Checking code should be modified if form element classes reside in a different location.

Now that we’ve analyzed in detail the factory class, let’s implement some examples to evaluate its functionality.

{mospagebreak title=Instantiating form element objects: a simple use of the form element factory}

Creating form element objects through the form element factory is a fairly straightforward process. Object instantiation is handled internally behind the interface of the class, so the code looks compact and readable. Let’s start factoring some form element objects, to clarify the usage of the factory:

$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′));

The above snippet simply creates several form objects. Note that object instantiation is performed behind the scenes, each time the “createElement()” method is invoked with the proper parameters. Since this method is static, it’s possible to call it outside the class context by using the (::) resolution scope operator.

If you think that the above examples are not complete, here is code to instantiate the rest of form element objects:

$radiobutton=formElementFactory::createElement
(‘radiobutton’,array
(‘name’=>’radio1′,’value’=>’1′,’checked’=>’true’));

$textarea=formElementFactory::createElement
(‘textarea’,array(‘name’=>’comments’,'value’=>’fill
this field’));

$checkbox=formElementFactory::createElement
(‘checkbox’,array
(‘name’=>’checkbox1′,’value’=>’1′,’checked’=>’true’));

$button=formElementFactory::createElement
(‘button’,array(‘name’=>’button1′,’value’=>’button’));

$submitbutton=formElementFactory::createElement
(‘submitbutton’,array
(‘name’=>’send’,'value’=>’Send’));

$resetbutton=formElementFactory::createElement
(‘resetbutton’,array
(‘name’=>’reset’,'value’=>’Reset’));

$selectbox=formElementFactory::createElement
(‘selectbox’,array
(‘name’=>’select’,'size’=>’1′,’options’=>array
(’1′=>’value1′,’2′=>’value2′)));

Finally, let’s implement a basic loop, for roughly rendering some objects:

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

After executing the above snippet, what you get is a crude visual presentation of the form elements included in the array. Of course, a more polished look is highly desired, but for the moment, let’s settle for the elements’ rendering process of this example.

As you can see, the defined “formElementFactory” class is doing its job quite well, despite its simplicity. Definitely, we’ve stepped forward to use the Factory Pattern within the form creation process, while the overall code has been maintained at a simple level.

Notice the evident separation between object instantiation and the rest of client code. There are no “new” constructs that indicate where the objects are created. The whole process is handled by the internals of the “formElementFactory” class.

There are still many aspects that need to be improved within the application, but you should remember that this is merely the beginning. The logic of the factory class must be modified, in order to get a higher level of abstraction to instantiate form objects, as well as get more control over visual presentation.

For many of these features to work, you’ll have to wait for the next part of the series. However, these are just a few ideas to get you started using the Factory pattern in real applications.

Wrapping up

Through this article, I’ve exposed the basics for implementing the Factory pattern in a real situation: building object-oriented forms. To fit this objective, a form element factory class has been defined, by showing that object instantiation can be completely decoupled from the client code, so a greater level of abstraction for rendering web-based forms is obtained within a program.

Over the next part of the series, I’ll add some features to the factory class, in order to encapsulate element rendering code within its structure. Meanwhile, play with the code and study its functionality. See you in the next part!

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