Patrones de diseño - Factory


Patrones de Diseño.

El patrón Factory, nos permitirá centralizar en una clase la creación de objetos de un mismo tipo. Definiremos una interfaz o una clase abstracta para crear un objeto, pero serán las subclases quienes decidan qué clase se va a instanciar, permitiendo que una clase delegue a sus subclases la creación de objetos. A continuación vamos a explicarlo más a fondo:

Clasificación

Creacional

Intención

Centraliza en una clase constructora la creación de objetos de un mismo subtipo de un tipo determinado.

Motivación

El patrónFactory es bastante útil cuando no se sabe de antemano que tipo de objeto de una familia se va a instanciar, sino que durante el proceso se decidirá que tipo hacerlo. Por ejemplo, procesar un fichero de configuración json, xml, yui, txt y es una variable la que nos indica que fichero se parseará.

Aplicabilidad

  • Una clase no puede prever la clase de objetos que debe crear
  • Centralizar la creación de objetos. Una clase quiere que sean sus subclases quienes especifiquen los objetos que ésta crea.
  • Delegar la responsabilidad en una de entre varias clases auxiliares, permitiendo crear una familia de objetos.

Estructura

Consecuencias

Proporciona más flexibilidad a la hora de crear objetos de una misma familia de objetos dentro de una clase.

Participantes

· Producto Define la interfaz de los objetos que crea el método de fabricación.
· Producto Concreto Implementa la interfaz del Producto.
· Creador Declara el método de fabricación que devolverá un objeto del tipo Producto. Puede definir una implementación predeterminada del método de fabricación.
· Creador Concreto Redefine el método de fabricación para devolver una instancia del Producto Concreto.

Implementación

La clase UserFactory tiene un método estático Create() que recibe como parámetro 2 argumentos. Según el valor de estos se decide que subclase se va a instanciar.

Código de ejemplo

Aunque existen bastantes variaciones del patrón Factory, las dos más utilizadas són:
- El creador es clase concreta que implementa una interfaz predeterminada para el método de creación.
- El creador es abstracto y no provee implementación par el método de creación.

Creador: es una Clase abstracta o Interfaz

Ahora vamos a mostrar varios ejemplos. En el primero, la Factory es una interfaz que crea las instancias GuestUser, ActiveUser y AdminUser, las cuales son denominadas productos en este tipo de patrón.
Clases User y subtipos: user.php
    /**
     * Clase abstracta User. De esta clase extenderá la familia 
     * de objetos de tipos de usuarios
     */
    abstract class User {
        protected $username = null;

        public function __construct($username) {
            $this->username = $username;
        }

        public function getPermissions() {
             return false;
        }

        public function getSuperPrivileges() {
             return false;
        }
    }

    // Clase GuestUser: User
    class GuestUser extends User {}

    // Clase ActiveUser: User
    class ActiveUser extends User {
        public getPermissions() {
            return true;
        }
    }

    // Clase AdminUser: User
    class AdminUser extends User {
        public getPermissions() {
            return true;
        }

       public function getSuperPrivileges() {
             return true;
        }
    }
    
Patrón Factory: user_factory.php
    
    /**
     * Creador sin implementación. Puede ser una inferface o 
     * una clase abstracta donde no se definan la implementación 
     * de los métodos de creación.
     */
    interface FactoryInterface {

         /** 
          * Método de creación.
          * 
          * @static
          * @param String $username Nombre de usuario
          * @param String $privilege Tipo de usuario. 
          * @access public
          */
        static public function Create($username, $privilege);
    }

    // UserFactory: FactoryInterface
    /**
     * Creador concreto que implementa la interfaz de creación.
     */
    class UserFactory implements FactoryInterface {

         // Datos "hardcoded" para realizar demostración
         private static $users = array(
             'jose'    => 'Guest',
             'jesus'   => 'Active',
             'zonadev' => 'Admin'
         );

         /** 
          * Método de creación. Retorna una instancia del objeto. Se obtiene que objeto
          * instanciar según el valor de $privilege.
          * 
          * @static
          * @param String $username Nombre de usuario
          * @access public
          */
        static public function Create($username) {
            if(isset(self::$users[$username])) {
                $privilege = self::$users[$username];

                $fry = ucfirst($privilege) . 'User';
                if(class_exists($fry)) {
                    return new {$fry}($username);
                } else {
                    throw new Exception('El tipo de usuario indicado no es correcto.');
                }
            } else {
                return new GuestUser($username);
            }
        }
    }
    
Ejemplo de implementación: privileges.php
    include_once 'user.php';
    include_once 'user_factory.php';

    function checkPermissions(User $o) {
        return $o->getPermissions();
    }
    
    function checkSuperPriivleges(User $o) {
        return $o->getSuperPrivileges();
    }

    echo checkPermissions(UserFactory::Create('zonadev'));
    echo checkSuperPrivileges(UserFactory::Create('zonadev'));
    
Próximamente añadiré más ejemplos con las diferentes formas de implementar la creación de objetos

Patrones relacionados

  • Patrón Abstract Factory

Referencias


0 comentarios:

Publicar un comentario