28 de julio de 2014

     El patrón Bridge desacopla una abstracción de su implementación, de forma que cada una de ellas pueda variar independientemente.

Aplicabilidad:
  • Desacoplar abstracciones de sus implementaciones permitiendo el cambio en tiempo de ejecución.
  • Necesidad de extender mediante herencia tanto la abstracción como sus implementaciones.
  • El cambio en la implementación de una abstracción no debería afectar a los clientes.
  • Necesidad de compartir una misma implementación.

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



Participantes:
  • Abstracción: Define la interfaz de la abstracción y mantiene la referencia al objeto implementador.
  • Abstracción refinada (AbstraccionRedefinida): Extiende la interfaz definida por la abstracción.
  • Implementador: Define la interfaz para los implementadores concretos. Esta interfaz no tiene porque corresponderse con la interfaz de la abstracción: (Implementador->primitivas, Abstracción->operaciones de alto nivel).
  • Implementador concreto (ImplementadorConcretoA, ImplementadorConcretoB): Implementa la interfaz Implementor definiendo una implementación concreta.

Colaboraciones:
     La abstracción redirige peticiones del cliente al objeto implementador


Concecuencias:
  • Desacoplamiento entre interfaz e implementación:
    • Elimina dependencias de compilación.
    •  Posibilidad de configuración en tiempo de ejecución.
  • Facilita el poder extender independientemente las jerarquías de abstracción e implementación.
  • Oculta los detalles de implementación a los clientes.

Implementación:    
  • Único implementador.
  • Creación del objeto implementador:
    • Si la abstracción conoce la jerarquía de implementadotes, entonces, puede crear el implementador en el constructor en base a sus parámetros.
    • Si la abstracción no conoce la jerarquía de implementadores entonces deberá delegar en otro objeto que se encargue de proporcionarle el implementador concreto, por ejemplo una Factoy.
  • Compartición de implementadores.

Patrones relacionados:
  • Abstract Factory: Permite crear y configurar un "Puente" particular
  • Adapter: Tiene como objetivo hacer trabajar juntas a clases con distinta interfaces, pero en general, se aplica a sistemas que existen. El patrón Bridge se suele aplicar al empezar un diseño, para permitir que las abstracciones e implementadores evolucionen independientemente. 

22 de julio de 2014

     El patrón Adapter permite la colaboración entre clases con interfaces incompatibles.
En otras palabras, adapta la interfaz de una clase de modo que esta nueva interfaz sea la que espera el cliente. El patrón Adapter ayuda a que dos clases con interfaces incompatibles puedan trabajar juntas. 


Aplicabilidad:
  • Se desea emplear una clase existente que no es compatible con la interfaz que se le requiere.
  • Se desea crear una clase reutilizable que coopere con clases no relacionadas.
  • Se desea usar diversas subclases existentes pero resulta impráctico adaptar sus interfaces mediante la extensión de todas ellas por lo que se emplea un objeto adaptador de la clase padre.

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



    Participantes:
    • Objetivo o Target (ITarget): Define la interfaz dependiente del dominio usada por el cliente.
    • Cliente: Colabora con los objetos de acuerdo con el interfaz Objetivo o Target.
    • Adaptado: Define una interfaz existente que necesita ser adaptada.
    • Adaptador: Adapta la interfaz del adaptado a la interfaz Objetivo

    Colaboraciones:
         El cliente envía mensajes al adaptador y éste en repuesta los envía al objeto adaptado.


    Concecuencias:
         En ocasiones, permite la incorporación de funcionalidades no disponibles en la clase adaptada.

    • Clase adaptadora:
      • No permite adaptar una clase y todas sus subclases.
      • La clase adaptadora permite redefinir parte del comportamiento del adaptado. 
    • Objeto adaptador:
      • Un adaptador permite adaptar a diversos objetos que poseen un antecesor común.
      • Difícil cambiar el comportamiento del adaptado. Para ello sería necesario extender el objeto adaptado y adaptar la nueva subclase.

    Implementación:
         Crear una nueva clase que será el Adaptador, que extienda del componente existente e implemente la interfaz obligatoria. De este modo, tenemos la funcionalidad que queríamos y cumplimos la condición de implementar la interfaz. 
    La diferencia entre los patrones Adapter y Facade, es que el primero reutiliza una interfaz ya existente, mientras que el segundo define una nueva con el objetivo de simplificarla.


    Patrones relacionados:
    • Bridge: Tiene una estructura similar al Adapter, pero con una funcionalidad diferente: Su propósito es separar la interfaz de su implementación así esta puede variar fácilmente y de forma independiente. En cambio, el propósito del Adapter es el cambio de interfaz de un objeto existente.
    • Decorator: Agrega responsabilidades a un objeto dinámicamente sin cambiar su interfaz. Un Decorator es más transparente a la aplicación que un Adapter, como consecuencia, soporta composición recursiva, lo cual, no es posible con el patrón Adapter.
    • Proxy: Define un punto de acceso para otro objeto, en dónde se controlara el acceso. Este tampoco cambia su interfaz.

    16 de julio de 2014

         Se asegura de que una clase determinada sólo tenga una única instancia y proporcione un punto de acceso a dicha instancia.


    Aplicabilidad:
    • Debe existir una única instancia de una clase, y ésta debe ser accesible a los clientes desde un punto de acceso bien conocido.
    • La única instancia puede ser extendida (subclase), y los clientes deberían poder usar la instancia extendida sin modificar su código.

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



    Participantes:
    • Singleton: Define un método de clase que permite a los clientes acceder a la instancia única y normalmente también es la responsable de crear su única instancia. 

    Colaboraciones:
          Los clientes acceden a la instancia del Singleton a través de la operación definida a tal fin (instancia()).


    Concecuencias:
    • Acceso controlado a la instancia única.
    • Reduce el espacio de nombres al evitar variables globales.
    • Permite el refinamiento de operaciones y representación mediante el uso de herencia. En este caso, en lugar de tener una única instancia de ella misma tiene una instancia única de una subclase, y esta usa la instancia de la subclase con la interface de la superclase.
    • Permite un número variable de instancias.
    • Más flexible que las operaciones de clase.

    Implmentación
    • Acceso controlado a la instancia única.
    • Asegurar la unicidad de la instancia de la clase.
    • Extender la clase Instancia Única o Singleton:
    • El método de clase instancia conoce las subclases de la jerarquía y crea la instancia deseada. 
    • Establecer algún mecanismo para registrar las subclases.

    Patrones relacionados:
    • Abstract Factory, Builder, Prototype: Única instancia de cualquiera de estos objetos o patrones

            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.




          2 de julio de 2014

               Define una interfaz para la creación de familias de objetos relacionados sin especificar sus clases concretas.


          Aplicabilidad:
          • Un sistema debe ser independiente de la forma en que sus productos son creados, compuestos y representados.
          • Un sistema debe ser configurado con una de muchas familias de productos disponibles.
          • Una familia de productos son diseñados para su uso conjunto, y se requiere asegurar este uso conjunto.
          • Se desea proporcionar una biblioteca de productos presentando su interfaz, pero no su implementación

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




          Participantes:
          • Fábrica abstracta (IFabrica): Declara la interfaz para las operaciones que crean productos abstractos (métodos de fabricación)
          • Fábrica concreta (Fabrica1, Fabrica2): Implementa los métodos de fabricación de productos concretos.
          • Producto abstracto (IProductoA, IProductoB): Declara la interfaz utilizada por el cliente para un tipo de producto concreto.
          • Producto concreto (ProductoA1, ProductoA2, ProductoB1, ProductoB2): Define un producto creado por el método de fabricación de una fábrica concreta. Implementa la interfaz del producto abstracto.
          • Cliente: Usa sólo las interfaces declaradas por la fábrica abstracta y los productos abstractos.

          Colaboraciones:
               Normalmente se crea una única fábrica concreta que se encarga de crear los productos concretos, mientras que la fábrica abstracta difiere la creación de productos a sus subclases.


          Concecuencias:
          • Aísla clases concretas (No aparecen en el código del cliente).
          • Facilita el intercambio de familias de productos.
          • Simplifica la consistencia entre productos.
          • Difícil de añadir nuevas clases de productos.

          Implementación:
          • Las fábricas usualmente suelen se instancias únicas.
          • La creación de productos puede realizarse por el método de fabricación habitual o mediante el patrón prototipo para evitar extender la fábrica abstracta.
          • Flexibilizar la fábrica mediante la parametrización del método de fabricación:
            • El método de fabricación puede crear diferentes tipos de componentes en base a los parámetros del método.
            • El cliente debe realizar una conversión tras crear el producto (downcasting).
            • En la mayoría de los lenguajes no hay ninguna relación formal entre valores de los parámetros y productos creados, exceptuando el código fuente.

          Patrones relacionados:
          • Factory Method o Prototype: El patrón Factory Abstract suele implementarse con métodos de fabricación, de la misma forma, puede implementarse con el patrón Prototype.
          • Singleton: Generalmente una fábrica concreta suele ser un Singleton.

            Subscribe to RSS Feed Follow me on Twitter!