CHAPTER 4 – Factory Pattern

4.4.3 Factory Pattern Polymorphism and the use of base class is really the center of OOP. However, at some stage, a concrete instance of the base class's subclasses must be cre- ated. This is usually done using the factory pattern. A Factory class has a static method that receives some input and, according to that input, it decides what class instance to create (usually a subclass). Say that on your web site, different kinds of users can log in. Some are guests, some are regular customers, and others are administrators. In a com- mon scenario, you would have a base class User and have three subclasses: GuestUser, CustomerUser, and AdminUser. Likely User and its subclasses would contain methods to retrieve information about the user (for example, permis- sions on what they can access on the web site and their personal preferences). The best way for you to write your web application is to use the base class User as much as possible, so that the code would be generic and that it would be easy to add additional kinds of users when the need arises. The following example shows a possible implementation for the four User classes, and the UserFactory class that is used to create the correct user object according to the username: abstract class User { function __construct($name) { $this->name = $name; } function getName() { return $this->name; } // Permission methods function hasReadPermission() { return true; } function hasModifyPermission() { return false;

} function hasDeletePermission() { return false; } // Customization methods function wantsFlashInterface() { return true; } protected $name = NULL; } class GuestUser extends User { } class CustomerUser extends User { function hasModifyPermission() { return true; } } class AdminUser extends User { function hasModifyPermission() { return true; } function hasDeletePermission() { return true; } function wantsFlashInterface() { return false; } } class UserFactory { private static $users = array("Andi"=>"admin", "Stig"=>"guest", "Derick"=>"customer"); static function Create($name) { if (!isset(self::$users[$name])) { // Error out because the user doesn't exist } switch (self::$users[$name]) { case "guest": return new GuestUser($name); case "customer": return new CustomerUser($name); case "admin": return new AdminUser($name); default: // Error out because the user kind doesn't exist } } } function boolToStr($b) { if ($b == true) { return "Yesn"; } else { return "Non"; } } function displayPermissions(User $obj) { print $obj->getName() . "'s permissions:n"; print "Read: " . boolToStr($obj->hasReadPermission()); print "Modify: " . boolToStr($obj->hasModifyPermission()); print "Delete: " . boolToStr($obj->hasDeletePermission()); } function displayRequirements(User $obj) { if ($obj->wantsFlashInterface()) { print $obj->getName() . " requires Flashn"; } } $logins = array("Andi", "Stig", "Derick"); foreach($logins as $login) { displayPermissions(UserFactory::Create($login)); displayRequirements(UserFactory::Create($login)); } Running this code outputs Andi's permissions: Read: Yes Modify: Yes Delete: Yes Stig's permissions: Read: Yes Modify: No Delete: No Stig requires Flash Derick's permissions: Read: Yes Modify: Yes Delete: No Derick requires Flash This code snippet is a classic example of a factory pattern. You have a class hierarchy (in this case, the User hierarchy), which your code such as displayPer- missions() treats identically. The only place where treatment of the classes dif- fer is in the factory itself, which constructs these instances. In this example, the factory checks what kind of user the username belongs to and creates its class accordingly. In real life, instead of saving the user to user-kind mapping in a static array, you would probably save it in a database or a configuration file. Tip: Besides Create(), you will often find other names used for the factory method, such as factory(), factoryMethod(), or createInstance().

Post Comment
Login to post comments