16 de julio de 2014

    El patrón prototipo crea objetos nuevos mediante la clonación de uno o varios prototipos almacenados. El patrón prototipo nos permite acelerar la creación de instancias muy grandes, mejorar la carga dinámica de clases (copia de objetos), y mantiene un registro de partes identificables de una gran estructura de datos que se pueden copiar sin saber la subclase de los que fueron creados.


Aplicabilidad:
  • Ocultar clases concretas del cliente.
  • Agregar y eliminar nuevas clases (a través de prototipos) en tiempo de ejecución.
  • Mantener un número minímo de clases en el sistema.
  • Adaptarse a los cambios en las estructuras de datos en tiempo de ejecución.

Estructura:
En la siguiente imagen podemos ver un diagrama UML de este patrón:


Participantes:
  • Prototipo (IPrototipo): Declara la interface para clonarse.
  • Prototipo concreto (PrototipoA, PrototipoB): Implementa la operación de
  • clonarse.
  • Cliente: Crea un nuevo objeto solicitándole al prototipo que se clone

Colaboraciones:     
            El cliente solicita a un objeto prototipo que se replique (se clone), es decir, que se cree una copia de si mismo.


Concecuencias:
  • Oculta las clases del producto al cliente.
  • Permite que el cliente trabaje con clases dependientes de la aplicación sin cambios en este.
  • Especificación de nuevos objetos mediante el cambio de sus valores.
  • Especificación de nuevos objetos mediante la variación de su estructura a través del cambio del prototipo de modo que el cliente no se vea afectado.
  • Reducción del número de subclases. El patrón prototipo permite instanciar un nuevo clon a partir del prototipo en vez de pedir al método de fabricación que cree una nueva instancia, por lo tanto, no necesita una jerarquía de clases creadoras.
  • Configuración dinámica de una aplicación. Es posible añadir y eliminar productos en tiempo de ejecución. Algunos entornos en tiempo de ejecución te permiten la carga de clases de forma dinámica. El patrón prototipo es la clave para explotar tales facilidades.

 Clonación profunda vs. Clonación superficial

            Entre las diferentes modalidades que se puede optar a la hora de implementar la clonación de un objeto prototipo, cabe destacar dos maneras de realizar la clonación: Superficial y Profunda.

            En la primera de ellas, un cambio sobre el objeto asociado con un clon afecta al objeto original, porque los objetos relacionados son los mismos (es decir, la clonación replica sólo el propio objeto y su estado, no sus asociaciones con terceros objetos), mientras que en la clonación profunda se clonan los objetos y también sus objetos relacionados.




Nota: ejemplo tomado de wikipedia: Prototype (Patrón de diseño)

Características de clonación y serialización en C#

     MemberwiseClone es un método que está disponible en todos los objetos. Copia los valores de todos campos y cualquier referencia y devuelve una referencia a la presente copia. Sin embargo, no hace copia de las referencias el objeto. Es decir, se realiza lo que se conoce como una copia superficial. Muchos objetos son simples, sin referencias a otros objetos, y por lo tanto las copias superficiales son adecuadas. A fin de preservar el valor completo del objeto, incluyendo todos sus subobjetos utilizar una copia profunda

     No es fácil escribir un algoritmo general para seguir todos los eslabones de una estructura y recrear la disposición de otras partes. Sin embargo, los algoritmos existen, y en el Framework. NET se encapsulan en un proceso llamado serialización. Los objetos se copian a un determinado destino y puede ser devuelto a nuestra voluntad. Las opciones de destino para la serialización son varias, incluidos los discos e Internet, pero la más fácil para serializar objetos pequeños es la misma memoria. Así, una copia en profundidad consiste en serializar y deserializar en un método.

     Un método genérico que funcione para todos los tipos de datos (List<T>) debe ser marcado como serializable. Esto lo logramos escribiendo sobre el nombre del atributo o método la palabra [Serializable ()]


Importante:  La serialización es parte del Framework. NET, no del lenguaje C#. 

NOTA:
La serialización de una estructura de objetos es posible sólo si todos los objetos referenciados  son serializable. Evite serializar un objeto que tiene una referencia a un "Recurso", como un controlador de archivo abierto o una conexión de base de datos.


Implementación:

Uso de un gestor de prototipos:
En este patrón surge el problema de quién crea los prototipos para proporcionárselos al cliente de modo que este no sea dependiente de las jerarquías. En general debe ser un objeto que tenga que conocer la jerarquía y se la proporcione a los clientes (puede haber más de uno), este objeto se conoce como el gestor de prototipos. El gestor de prototipos tiene que proporcionar al cliente métodos para que el cliente seleccione el prototipo que estime oportuno, por ejemplo un método Producto crea (String tipoObjeto,  otra Información). Si en lugar de pasar un simple String con un nombre se establecen especificaciones más complejas, el patrón prototipo degenerará un Negociador de productos en donde el negociador es un gestor de prototipos.



Implementación de la opración de clonación:
En los objetos compuestos esto puede ser un problema. Por ejemplo, si clonamos un objeto decorado (ver patrón decorador) de qué se hace copia del envoltorio exterior o de todo el conjunto, es decir, copia las referencias o crea nuevos objetos para el estado. En función de la decisión que se tome se modificará la operación clonar(). 

Iniciación del objeto clonado:
Inicialización del objeto clonado en caso de que la réplica necesite una inicialización adicional. A veces no es factible crear la instancia y replicar todo el estado del objeto que sirve como prototipo. Por ejemplo, en el caso de que el prototipo tenga una clave o identificador de instancia o si hay una cierta parte del prototipo que no se puede clonar. Cuando se requiere de una inicialización la opción más común puede ser:

Exportar a la superclase los métodos de inicialización. Esta opción es válida si todas las figuras en la jerarquía tuviesen la misma interface para realizar su inicialización. Ejemplo: void inicializar (string fich_xml). Cada subclase debe redefinir el método y extraer la información necesaria.


Patrones relacionados:
  • Composite: El patrón Prototype es utilizado a menudo con el patrón Composite.
  • Abstract Factory: El patrón Abstract Factory puede ser una buena alternativa al patrón
  • Facade: La clase cliente normalmente actúa comúnmente como un Facade que separa las otras clases que participan en el patrón Prototype del resto del programa.
  • Factory Method: El patrón Factory Method puede ser una alternativa al patrón Prototype cuando la paleta de objetos prototipo nunca contiene más de un objeto.
  • Decorador: El patrón Prototype es utilizado a menudo con el patrón Decorator.




    Subscribe to RSS Feed Follow me on Twitter!