PHP
  Home arrow PHP arrow Page 4 - Design Patterns in PHP - Factory Metho...
Dev Shed Forums 
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Sun Developer Network 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Moblin 
JMSL Numerical Library 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

Design Patterns in PHP - Factory Method and Abstract Factory
By: David Fells
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 62
    2004-12-20

    Table of Contents:
  • Design Patterns in PHP - Factory Method and Abstract Factory
  • Factory Method
  • Abstract Factory
  • Drawbacks of the Example
  • Conclusion

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Design Patterns in PHP - Factory Method and Abstract Factory - Drawbacks of the Example


    (Page 4 of 5 )

    Now that you understand the example case, we need to talk about the drawbacks with the implementation used in this example. The main roadblock with using this implementation is that the MazeGame object is hard coded to create specific classes of objects - that is, it creates Maze, Wall, Door and Room directly without use of any factory methods. We can improve this design by refactoring our createMaze method to use a MazeFactory object for object instantiation. Here is an example.

    class MazeFactory {
      function MazeFactory() {}
      function createMaze() { return new Maze(); }
      function createRoom($roomNumber) { return new Room($roomNumber); }
      function createDoor($room1, $room2) { return new Door($room1, $room2); }
      function createWall() { return new Wall(); }
    }

    class MazeGame {
      function createMaze() {
        $factory = new MazeFactory();
        $aMaze = $factory->makeMaze();
        $room1 = $factory->makeRoom(1);
        $room2 = $factory->makeRoom(2);
        $aDoor = $factory->makeDoor($room1, $room2);
       
        $room1->setSide(North, $factory->makeWall());
        $room1->setSide(East, $aDoor);
        $room1->setSide(South, $factory->makeWall());
        $room1->setSide(West, $factory->makeWall());           

        $room2->setSide(North, $factory->makeWall());
        $room2->setSide(East, $factory->makeWall());
        $room2->setSide(South, $factory->makeWall());
        $room2->setSide(West, $aDoor);                         
       
        $aMaze->addRoom($room1);
        $aMaze->addRoom($room2);
      }
    }

    This method is significantly better because it moves creational knowledge out of the createMaze() method and into the MazeFactory class. This will work fine if we only want to use one family of Maze objects, but what if we want to create subclasses of Wall, Door and Room to allow different behaviors? The examples given in Design Patterns use enchanted rooms and rooms with bombs as examples.

    An enchanted room could have special behaviors, such as requiring conditions to be met before a door could be opened or closed. A room with a bomb would know what conditions caused a bomb to detonate and would track whether or not the bomb had gone off. If the bomb had gone off, it would keep up with damage to walls from the bomb. If we wanted to use these classes, we would have to parameterize our factory object to check some sort of input condition to know which family of objects to create.

    This is where the Abstract Factory pattern comes in. This pattern uses the Factory Method pattern to handle actual object instantiation, but the value of the Abstract Factory pattern comes at a higher level. We code our calling code not only to use factory methods for object creation but to expect a factory object that conforms to a certain interface. This means that we can use different factories - all based on a single abstract factory interface - to create different families of objects. Calling code would only need to expect a class that derives from the original MazeFactory class.

    For brevity's sake we will not type out the code to define the subclasses of Room, Wall, and Door, but we will define the subclasses of the MazeFactory object that are used to create enchanted mazes and mazes with bombs in them.

    class EnchantedMazeFactory extends MazeFactory {
      function makeRoom($roomNumber) { return new EnchantedRoom($roomNumber); }
      function makeDoor($room1, $room2) { return new EnchantedDoor($room1, $room2); }
    }

    class BombedMazeFactory extends MazeFactory {
      function makeRoom($roomNumber) { return new RoomWithABomb($roomNumber); }
      function makeWall() { return new BombedWall(); }
    }

    We can now use different concrete factory classes to create different families of products - in this case, different types of Doors, Walls, and Rooms. We are now left with one last problem - createMaze(), at last glance, is hard coded to create a MazeFactory object. Since createMaze() only needs to create the objects themselves through a standard factory interface, there is no need for the method to ever actually create the factory. We should pass the factory in as an argument to createMaze() and then let the method do its work.

    class MazeGame {
      function createMaze($factory) {
        $aMaze = $factory->makeMaze();
        $room1 = $factory->makeRoom(1);
        $room2 = $factory->makeRoom(2);
        $aDoor = $factory->makeDoor($room1, $room2);
       
        $room1->setSide(North, $factory->makeWall());
        $room1->setSide(East, $aDoor);
        $room1->setSide(South, $factory->makeWall());
        $room1->setSide(West, $factory->makeWall());           

        $room2->setSide(North, $factory->makeWall());
        $room2->setSide(East, $factory->makeWall());
        $room2->setSide(South, $factory->makeWall());
        $room2->setSide(West, $aDoor);               
       
        $aMaze->addRoom($room1);
        $aMaze->addRoom($room2);
      }
    }

    Now in our createMaze() method, no assumptions are made about the type of factory we need. Some other code that is responsible for figuring out what type of factory to create would actually instantiate the MazeFactory and pass it to createMaze(), as in the following example.

    $game = new MazeGame();
    $game->createMaze(new EnchantedMazeFactory());

    After all is said and done, we have created (with a little help from Design Patterns) a very flexible set of classes for producing mazes. It should be noted that in an actual implementation, createMaze() would be using data of some kind to determine what components are required in the maze and the method calls on the various MapSite objects would not be hard coded as they are in the example.

    More PHP Articles
    More By David Fells


       · I'm pretty new to Design Patterns in General. On the first page, the two described...
       · DP is a reference to the book "Design Patterns". 87 and 107 are the pages where the...
       · To be more...
       · I see, thanks! ...
       · I really enjojed this article may be you do do some more on other patterns
       · My plan is to write a series on Design Patterns in PHP but at the moment, article...
       · On page 4/5 of the article, the methods in MazeFactory class are createMaze,...
       · Great article. I gave it 5 stars.Something I'm working on right now will have a...
       · very good article. Helped me understand the difference and see the benfits of the 2...
       · this article is really useful for those who are new to design patterns.
       · Very good article, I really understood something from it.
     

       

    PHP ARTICLES

    - Validating Web Forms with the Code Igniter P...
    - Output Buffering
    - Paginating Database Records with the Code Ig...
    - HTTP Headers in Web Development
    - Project Management: Administration
    - Building a Database-Driven Application with ...
    - User Authentication for a Project Management...
    - Introduction to the CodeIgniter PHP Framework
    - Adding Users for a Project Management Applic...
    - Migrating Class Code for a MIME Email to PHP...
    - Login and Logout Authentication for a Projec...
    - Composing Messages in HTML for MIME Email wi...
    - Project Management: Authentication
    - A Better Way to Determine MIME Types for MIM...
    - Project Management Overview





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway