The Basics of Abstract Factory Classes in PHP 5

You have probably used the factory design pattern before. An abstract factory pattern helps you make sure you’re creating the correct objects for your application according to the context. This article, the first one in a three-part series, gives you a taste of what you can do with the abstract factory pattern. As always, it includes plenty of examples.

Introduction

If you’ve been using pattern-based programming with PHP for a while, then it’s highly probably that you’ve already implemented the factory design pattern as part of the business logic that drives your web applications.

As you’ll certainly know, building a factory class can be useful in certain situations. It can be particularly useful when you need to spawn a number of objects across a given application without having to worry too much about how these objects are created by the class in question. However, one thing is true for this class in particular: no matter how many objects are returned to client code, they always conform to the expectations of a predefined context.

In simpler terms, this implies that if you’re going to build, for instance, online forms by using a form element factory class, this class will be used in an environment where these types of objects are expected by the application. Nonetheless, this design pattern should work well as long as you know the context where all the spawned objects are going to work. But what happens if you’re trying to develop a PHP application that uses multiple contexts?

Say you’re building a system that generates dynamic web pages, and all of their elements are created by using a factory class. Obviously, in this case, the type of objects returned to client code will depend completely upon the kind of web document being created, right? You can’t simply spawn form objects in a web page where there isn’t any online form to be included. Period.

So, there must be some way other than using a concrete factory class that allows you to create correct objects according to the context a PHP application is using for a particular instance. Naturally, this leads us straight to the implementation of another pattern, which is widely known as "abstract factory."

When the abstract factory pattern is applied, obviously there’s an abstract factory class that defines the type of objects that will be created by the corresponding concrete factories (in other words, non-abstract). On its side, a concrete factory class is responsible for spawning the correct kind of objects that correspond to its context. This implies that, if an application uses multiple contexts, the non-abstract factory always will return to client code an object that conforms to the expectations of a given instance.

Does this sound a bit confusing? Fear not, because in this three-part series, I’m going to show you how to create an abstract factory class with copious friendly hands-on examples. Hopefully, by the end of this series, you should have a more intimate knowledge of how this useful pattern works.

With the preliminaries out of our way, let’s learn together the basics of applying the abstract factory pattern with PHP 5. Let’s go!

{mospagebreak title=Introducing the abstract factory pattern: defining an abstract web page element factory}

In consonance with the concepts that you just read in the introduction, first I’m going to define an abstract factory class aimed at creating generic web page elements. As you’ll see shortly, this class will define what web page objects will be created by two concrete factories, in this way implementing the schema required by the factory pattern.

Having explained the purpose of defining this abstract factory class  for creating web page objects, here is its signature:

// define abstract ‘WebPageElementFactory’ class
abstract class AbstractWebPageElementFactory{
   abstract public function createWhiteDivElement();
   abstract public function createBlackDivElement();
}

As you can see, the abstract factory class defines clearly what type of objects must be created by two additional concrete factories. In this case, these two non-abstract classes will be tasked with spawning two specific kind of objects: white and black DIV elements respectively.

However, the signature for the above abstract class does not say much about how to implement the abstract factory pattern. Therefore. let me go one step further and derive two subclasses from the abstract one. these will offer a concrete implementation for creating different types of DIV elements.

Having said that, the respective definitions for these two new subclasses are as follows:

// define concrete ‘SmallDivElementFactory’ class
class SmallDivElementFactory extends AbstractWebPageElementFactory{
   private $content=’small';
   public function createWhiteDivElement(){
    return new SmallWhiteDivElement;
   }
   public function createBlackDivElement(){
     return new SmallBlackDivElement;
   }
}
// define concrete ‘LargeDivElementFactory’ class
class LargeDivElementFactory extends AbstractWebPageElementFactory{
   private $context=’large';
   public function createWhiteDivElement(){
     return new LargeWhiteDivElement;
   }
   public function createBlackDivElement(){
     return new LargeBlackDivElement;
   }
}

You’ll definitely agree with me that things are getting really interesting! Please, notice how the two previous concrete factory classes first define the respective contexts where they’re going to work, that is "small" and "large," and then return to client code the correct DIV objects.

In the first case, the factory class insures that either a black or white DIV object will be always created in the "small" context, while in the second case, objects will be spawned in the "large" environment. Now, are you starting to grasp the logic behind the abstract factory pattern? I hope you are!

Okay, at this point I have shown you how the abstract factory looks, as well as how the respective concrete factories were defined. Therefore I think it’s time to move forward and proceed to create the group of classes that are tasked with generating black and white DIV objects according to the respective contexts.

Do you want to see how these factory classes will be defined? All right, jump into the following section and keep reading. I’ll be there, waiting for you.

{mospagebreak title=Creating small and large DIV objects}

After defining all the concrete factory classes that you learned in the previous section, the next step consists simply of creating a new set of classes that logically display small and large DIV elements. Of course, the pertinent definitions for these brand new classes are easy to follow, and are listed below. So, have a look at them, please:

// define abstract ‘DivElement’ class
abstract class DivElement{
   abstract function display();
}
// define concrete ‘SmallWhiteDivElement’ class
class SmallWhiteDivElement extends DivElement{
   private $style=’width: 100px; background: #fff; border: 1px solid #999;';
   private $content=’This is the content of the small DIV element';
   public function display(){
     return ‘<div style="’.$this->style.’">’.$this-
>content.'</div>';                      
   }
}
// define concrete ‘SmallBlackDivElement’ class
class SmallBlackDivElement extends DivElement{
   private $style=’width: 100px; background: #000; color: #fff; border: 1px solid #999;';
   private $content=’This is the content of the small DIV element';
   public function display(){
     return ‘<div style="’.$this->style.’">’.$this-
>content.'</div>';                      
   }
}
// define concrete ‘LargeWhiteDivElement’ class
class LargeWhiteDivElement extends DivElement{
   private $style=’width: 500px; background: #fff; border: 1px solid #999;';
   private $content=’This is the content of the large DIV element';
   public function display(){
     return ‘<div style="’.$this->style.’">’.$this-
>content.'</div>';                      
   }
}
// define concrete ‘LargeBlackDivElement’ class
class LargeBlackDivElement extends DivElement{
   private $style=’width: 500px; background: #000; color: #fff; border: 1px solid #999;';
   private $content=’This is the content of the large DIV element';
   public function display(){
     return ‘<div style="’.$this->style.’">’.$this-
>content.'</div>';                      
   }
}

As illustrated above, the four previous classes are responsible for returning (to calling code) the correct (X)HTML markup that renders a specific DIV element. In the first two cases, the aforementioned classes will display small DIVs, while on the other occasions, only large DIVs will be created. Pretty simple, right?

All right, now you have learned how to create an abstract factory class which is capable of indicating what DIV objects should be spawned by the respective concrete factories, in accordance with their corresponding contexts. Nevertheless, I believe firmly that you’ll understand the functionality of all these classes more easily if I set up an illustrative example where they can be put to work conjunctly.

Taking this fact into account, I suggest that you go ahead and read the next few lines, since you’re just about to see the real power of the abstract factory pattern!

{mospagebreak title=Seeing the abstract factory pattern in action}

As I expressed in the previous section, undoubtedly the best way to see how all the previous factory classes fit each other, is by setting up an educational example where they can work together.

The main objective here is to demonstrate how each of the concrete factory classes defined previously can create a correct DIV object in consonance with its respective context. After all, this is the foundation upon which the abstract factory pattern is based.

All right, now that you know how each of the factory classes should work, please pay attention to the following hands on example. It demonstrates in a nutshell, the functionality of the abstract factory pattern. Here is the corresponding code listing, so have a look at it:

try{
   // instantiate ‘SmallDivElementFactory’ object (works in the ‘small’ context)
   $factoryInstance=new SmallDivElementFactory();
   $smalldiv1=$factoryInstance->createWhiteDivElement();
   $smalldiv2=$factoryInstance->createBlackDivElement();
   // displays small DIVS
   echo $smalldiv1->display();
   echo $smalldiv2->display();
   // instantiate ‘LargeDivElementFactory’ object
   // (works in the ‘large’ context)
   $factoryInstance=new LargeDivElementFactory();
   $largediv1=$factoryInstance->createWhiteDivElement();
   $largediv2=$factoryInstance->createBlackDivElement();
   // display large DIVS
   echo $largediv1->display();
   echo $largediv2->display();
}
catch(Exception $e){
   echo $e->getMessage();
   exit();
}

As you can see, the above example is indeed very demonstrative, since it shows how the schema imposed by the abstract factory pattern really works. In this case, you’ll realize that each instance of a concrete factory class knows perfectly how to create white and black DIV objects, depending on the context where these factories are used.

Also, with reference to the previous example, once a "SmallDivElementFactory" class has been properly instantiated, two small DIVs are created and displayed on the browser, since this factory instance works in the respective "small" context.

Similarly, when an instance of the "LargeDivElementFactory" class is spawned, the pair of DIVs displayed in this case are logically large elements, since the factory instance works in the "large" context. Quite simple, right?

At this stage, I’m pretty certain that you understand how the abstract factory pattern works, since the previous example is clear enough. However, as with other topics that deal with high levels of abstraction, I suggest that you create your own examples based on the pattern schema that I showed here. I’m sure that the experience will be instructive.

Final thoughts

In this first article of the series, I demonstrated how to develop a few simple factory classes, which came in handy for implementing the abstract factory pattern with PHP 5.

However, we’re just beginning to explore this huge subject, since in the next part I’ll show you how to apply this useful pattern to work with different instances of AJAX HTTP requester objects. So, if you’re interested in learning how this will be achieved, don’t miss that tutorial!  

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

chat sex hikayeleri Ensest hikaye