The Factory Design Pattern

After years of hacking around with OOP, MVC, MVVM etc. I’ve decided to gather some usefully distinct examples of design patterns, and create a few of my own with metaphors that work for me.

Today’s pattern; The Factory.

The Factory pattern allows you to more loosely couple the different parts of your application code.

For instance: A class that needs to create a new User shouldn’t have to care (too much) when the definition of “User” changes – subtly or drastically. The Factory pattern grabs the request to build a new user, worries about the details of the job, whirrs away for a few nanoseconds, and drops a shiny new User into the application’s workspace, ready to be used by the original class.

If the first version of the application needs a user with properties like Gender, Age and Name, we can set up those properties’ initial values as the User is created in the Factory.

If the upgraded application needs to add Favourite Colour, Favourite Animal, Mother’s Name to the definition of a User, all we need to do is alter the Factory; no other code needs to change. We could even redirect the Factory to a new, alternate user-creation class.

 

First an example in PHP:

#!/usr/bin/php5.3 -d display_errors=On -c /Applications/MAMP/bin/php/php5.3.20/conf/
<?php
/**
Different php binaries and conf directories for various MAMP php-cli versions 
(chmod+x factory.php, then run it from the command line as: ./factory.php):
 
#!/usr/bin/php5.2 -d display_errors=On -c /Applications/MAMP/bin/php/php5.2.17/conf/
#!/usr/bin/php5.3 -d display_errors=On -c /Applications/MAMP/bin/php/php5.3.20/conf/
#!/usr/bin/php5.4 -d display_errors=On -c /Applications/MAMP/bin/php/php5.4.10/conf/
**/
error_reporting(E_ALL | E_STRICT);
print "PHP Version: ".phpversion()."\n";
 
interface IUser
{
  function getId();
  function getName();
  function getGender();
}
 
class User implements IUser
{
  public function __construct( $id ) {
    $this->id = $id;
    if ($this->id > 100)
      {
	$this->name = "Jack";
	$this->gender = "Male";
      }
    else
      {
	$this->name = "Jill";
	$this->gender = "Female";
      }
  }
 
  public function getId()
  {
    return "id was ".$this->id;
  }
 
  public function getName()
  {
    return $this->name;
  }
 
  public function getGender()
  {
    return $this->gender;
  }
}
 
class UserFactory
{
  public static function Create( $id )
  {
    return new User( $id );
  }
}
 
$u0 = UserFactory::Create( 99 );
echo( $u0->getName()."\n" );
echo( $u0->getId()."\n" );
echo( $u0->getGender()."\n" );
echo( "Direct reference to u0->id: ".$u0->id."\n" );
$u1 = UserFactory::Create( 102 );
echo( $u1->getName()."\n" );
echo( $u1->getId()."\n" );
echo( $u1->getGender()."\n" );
echo( "Direct reference to u1->id: ".$u1->id."\n" );
echo( "All done" );
 
//borrowed *heavily* from http://www.ibm.com/developerworks/library/os-php-designptrns/
 
?>