Patrones de diseño - Factory

0 comentarios


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


Patrones de diseño

2 comentarios

Que són los Patrones de diseño del Software

En el mundo de la programación escuchamos bastante a menudo hablar sobre "Patrones de diseño" y la primera vez, las preguntas que nos hemos hecho todos son las mismas. ¿Qué son y para qué sirven?
Podemos definir un patrón de diseño, como una base para la búsqueda de soluciones a problemas que encontramos comúnmente durante el desarrollo de software. Para que una solución sea considerada un patrón, debe haberse demostrado en otras ocasiones su efectividad y que esa misma solución es reutilizable para cualquier situación similar.
Podemos encontrar 3 tipos fundamentales de patrones: de creación, estructurales y de comportamiento, además de un cuarto tipo que utilizaremos para aplicaciones concurrentes. Paso a listar los patrones más conocidos.
En futuros posts, iré explicando los patrones uno por uno, con ejemplos de implementación y explicando cuando y porqué los utilizaremos. No lo hago en este post directamente porque se haría demasiado largo y pesado de leer, así que he preferido ir paso a paso y hacer primero una primera introducción.

Relación de Patrones:

  • 1 Patrones de creación
    • 1.1 Patrón Factory (Factoría)
    • 1.2 Patrón Abstract Factory (Factoría Abstracta)
    • 1.3 Patrón Builder (Constructor)
    • 1.4 Patrón Singleton (Instancia 
      • Shallow copy
      • Deep Copy
    • 1.5 Patrón Prototype (Prototipo)
    • 1.6 Patrón Lazy initialization
    • 1.7 Patrón Multiton
    • 1.8 Patrón Object Pool
  • 2 Patrones estructurales
    • 2.1 Patrón Adapter (Adaptador)
    • 2.2 Patrón Bridge (Puente)
    • 2.3 Patrón Composite (Composición)
    • 2.4 Patrón Decorator (Decorador)
    • 2.5 Patrón Facade (Fachada)
    • 2.6 Patrón Front Controller
    • 2.7 Patrón FlyWeight
    • 2.8 Patrón Proxy
    • 2.9 Patrón Module
  • 3 Patrones de comportamiento
    • 3.1 Patrón Blackboard
    • 3.2 Patrón Chain of responsibility (Cadena de Responsabilidad)
    • 3.3 Patrón Command (Comando)
    • 3.4 Patrón Interpreter (Intérprete)
    • 3.5 Patrón Iterator (Iterador)
    • 3.6 Patrón Mediator (Mediador)
    • 3.7 Patrón Memento (Recuerdo)
    • 3.8 Patrón Null Object
    • 3.9 Patrón Observer (Observador)
    • 3.10 Patrón Servant
    • 3.11 Patrón Specification
    • 3.12 Patrón State (Estado)
    • 3.13 Patrón Strategy (Estrategia)
    • 3.14 Patrón Template (Plantilla)
    • 3.15 Patrón Visitor (Visitante)
  • 4 Patrones para aplicaciones concurrentes
    • 4.1 Patrón Active Object
    • 4.2 Patrón Balking
    • 4.3 Patrón Binding properties
    • 4.4 Patrón Messaging design pattern (MDP)
    • 4.5 Patrón Double-checked locking
    • 4.6 Patrón Event-based asynchronous
    • 4.7 Patrón Guarded suspension
    • 4.8 Patrón Lock
    • 4.9 Patrón Monitor object
    • 4.10 Patrón Reactor
    • 4.11 Patrón Read-write lock
    • 4.12 Patrón Scheduler
    • 4.13 Patrón Thread pool
    • 4.14 Patrón Thread-specific storage
    • 4.15 Patrón Unit of Work
Referencias:
Para estudiar todo el tema de patrones, estoy utilizando la información disponible en los siguientes enlaces, los cuales os recomiendo si queréis meteros a fondo en el estudio de patrones de diseño: