Saturday, 15 October 2016

PHP Factory pattern

What is a Factory?

A factory is in essence a function that returns an instance of an object of the desired type when the class type that you want is unknown. For instance, let's say you have a Staff class with Teacher and Janitor sub-classes. When you fetch the list of all user's from the database and you want to loop through them and create the correct object type for each user without having to write an if-block each time you want to do this. This is where a Factory comes in.

A simple Factory

Again, assuming we have a Staff class with Teacher and Janitor sub-classes:

class Staff {
  public $staffType = 'Staff';
}

class Teacher extends Staff {
  public $staffType = 'Teacher';
}

class Janitor extends Staff {
  public $staffType = 'Janitor';
}
We now want to create a new staff-member object without writing an if block each time, let's build a Factory.
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    if ($type === 'teacher') {
      return new Teacher();
    } elseif ($type === 'janitor') {
      return new Janitor();
    } else {
      return new Staff();
    }
  }

}
When we want to create an instance of a new staff-member object we can use:
$teacher = StaffFactory::buildStaffMemberObject('teacher');
$janitor = StaffFactory::buildStaffMemberObject('janitor');
That's it, you have a working Factory that builds objects of the correct type for you.

A more complex Factory

The above example works, but it's lacking in flexibility. Every time you want to add a new type you are going to have to add another condition inside the if/else if block. What if we had a Factory that could dynamically figure out which class type to load, let's take a look:
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    $className = ucfirst($type);
    $className = class_exists($className) ? $className : 'Staff';
    return new $className();
  }

}
This time we are checking whether a class by the given name exists in the current namespace, otherwise we default back to 'Staff'. This way when you create a new staff member type, for example, "Management", all you have to do is create and include the class in you script and you can immediately create it via your Factory.

No comments:

Post a Comment