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.

                 Este patrón es también conocido cómo Constructor virtual.
                 Define un interfaz para crear un objeto, dejando que sean las subclases quiénes decidan que clase concreta se debe instanciar. 


            Aplicabilidad:
            • No se puede anticipar la clase de objetos que se tienen que crear.
            • Una clase quiere que sus subclases especifiquen que objetos se deben crear.
            • Clases que delegan la responsabilidad a una de las subclases colaboradoras y se desea localizar el conocimiento de que subclase es la encargada

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



            Participantes:
            • IProducto: Define la interfaz de los objetos creados por el método de fabricación.
            • ProductoA y ProductoB: Clases que implementan la interfaz IProducto
            • Creador o Factory method: Declara el método de fabricación y opcionalmente puede definir una implementación por defecto que construye un producto concreto. 

            Colaboraciones:
                 El creador emplea el método de fabricación redefinido por sus subclases para utilizar la instancia del producto concreto apropiada


            Concecuencias:
                 El diseño de este patrón permite que la decisión de fabricación de un producto que va a ser instanciado se realice en un solo lugar. 
                  Si el cliente conociera todas las opciones de creación, las decisiones para eligir que producto crear se realizarían por todo el código. De esta forma, el cliente solo deberá preocuparse en la obtención de productos, sin tener en cuenta las subclases que intervienen en la creación.
                 También el cliente puede tener más de un creador para los diferentes tipos de productos. 
                 Obtendremos mayor flexibilidad dado que se proporciona un mecanismo a las subclases para introducir una versión más extendida del producto.

            Desventaja: Puede obligar a extender la clase creadora sólo para crear un producto concreto. Si esto es un problema puede emplear otra solución como por ejemplo el patrón Prototype.


            Implementación:

            Dos variantes:
            • El creador es una clase abstracta y no proporciona implementación por defecto para el método (necesario extender al creador)
            • El creador es una clase concreta y define un producto concreto por defecto (flexibilidad para cambios futuros).

            Métodos de fabricación parametrizados:
            Un único método puede crear distintos productos en base a los parámetros del método de fabricación. (Solución más común.).    


            Patrones relacionados:
            • Abstract Factory: Este patrón suele implementarse con métodos de fabricación.
            • Template Method: Los métodos que generalmente son llamados desde adentro del patrón son Template Method.
            • Ptrototype: El creador necesita una operación para inicializar la clase producto.





            24 de enero de 2014

            Este patrón es también conocido cómo Builder
            Separa la construcción de un objeto complejo de su representación, de modo que el mismo proceso de construcción permite crear diferentes representaciones.


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

            Participantes:
            • Constructor o Builder (IBuilder): Especifica la interfaz para la creación de las partes de un Producto.
            • Constructor concreto (Builder): Implementa la interface del constructor para construir y ensamblar las diferentes partes del producto. Además almacena el producto en construcción y proporciona una interfaz para recuperar el producto construido.
            • Director: Construye un objeto utilizando la interfaz del constructor.
            • Producto: Objeto concreto a construir.

            Colaboraciones:
            • El cliente crea el objeto director y lo configura con el constructor deseado.
            • El director notifica al constructor la parte del producto que debe ser creada.
            • El constructor añade partes al producto, de acuerdo con las peticiones del director.
            • El cliente recupera el producto final del constructor.



            Concecuencias:
            • Permite variar la representación interna de un producto.
            • Aísla el código de la construcción y la representación.
            • Proporciona un control más detallado del proceso de construcción.

            Implementación:
                  En el nivel más elemental, es posible implementar un patrón Builder básico con una única clase Builder que tenga un método de creación y su producto. Para dotarlo de mayor flexibilidad, los diseñadores suelen ampliar este patrón básico con una o más de las siguientes opciones:

            • Crear un Builder abstracto. Puede tener un sistema más genérico que sea capaz de albergar muchos tipos distintos de constructores si define una clase abstracta o una interfaz que especifique los métodos de creación.
            • Definir múltiples métodos de creación para el Builder. Algunos Builder definen varios métodos de creación (básicamente, sobrecargan su método de creación) para proporcionar distintas formas de inicializar el recursos construido.
            • Crear delegados para la creación. Con esta variante, un objeto Director contiene el método de creación general del Producto y llama a una serie de métodos mas granulares en el objeto Builder. En este caso, el objeto Director actúa como gestor para el proceso de creación del Builder.

            Patrones relacionados:
            • Abstract Factory: El patrón Builder puede ser remplazado con el patrón Abstract Factory para la creación de objetos complejos. Si bien, el patrón Builder se centra en la construcción de objetos complejos paso a paso, el patrón Abstract Factory hace hincapié en familia de objetos.
            • Composite: Muchas veces lo que construye el patrón Builder es un Composite.

            Les dejo un ejemplo que descargar en C#: Builder_Pattern

            17 de enero de 2014

                 El término “Happy Pattern" apareció por primera vez en el libro “Refactoring to Patterns”. Este término fue utilizado como calificativo aplicado a un programador que utiliza un patrón de manera indiscriminada sin tener en cuenta si este patrón proporciona algún beneficio al diseño, o por el contrario, si este patrón nos lleva a la construcción de un mal diseño.

                 Cuando utilizamos un patrón debemos tener en cuenta los beneficios y las consecuencias que implica su uso. Mientras que los patrones nos da una mayor flexibilidad a nuestros diseños. Estos también añaden más complejidad en ellos.

                 Siempre debemos considerar que los patrones son un buen punto de partida o de referencia, pero estos no son fundamentos incuestionables.



            15 de enero de 2014

                 Todas las disciplinas tienen buenos y malos usos, en este caso “Patrones” y “Antipatrones”. Si un patrón es una buena práctica, entonces, un antipatrón es una mala práctica.

            Existen dos tipos de antipatrones:
            1. Aquellos que describen una mala solución a un problema y que da como resultado una mala situación.
            2. Aquellos que describen como salir de una mala situación y convertirla en una buena solución.

                 Los antipatrones son considerados una parte importante del conocimiento, en otras palabras, es muy importante conocer y entender las buenas soluciones y las malas soluciones.
                        Los diseñadores intentan evitar los antipatrones siempre que sea posible, pero para esto se debe poder reconocerlos e identificarlos lo antes posible. Los antipatrones más útiles son aquellos que no permiten rehacer un buen diseño a partir de uno malo.
                        El concepto de antipatrón puede encontrarse en muchas disciplinas. Pero es ampliamente utilizado en la ingeniería en general.
            Se puede definir entonces a un antipatrón de la siguiente forma:

            “Forma literaria que describe una solución comúnmente dada a un problema que genera consecuencias negativas decididamente”.


            Para la ingeniería del software se pueden clasificar los siguientes tipos de antipatrones

            Antipatrones de desarrollo de software:
            1. The Blob (“Clases gigantes”).
            2. Lava Flow (“Código muerto”).
            3. Funcional Fecomposition (“Diseño no orientado a objetos”).
            4. Poltergeists (“No se sabe bien lo que hacen algunas clases”).
            5. Golden hammer (“Para un martillo todo son clavos”).
            6. Spaghetti code (“Muchos if o switch”).
            7. Cut-and-paste programming (“Cortar y pegar código")

            Antipatrones de arquitectura de software:
            1. Stovepipe enterprise ("isolation in the company").
            2. Stovepipe system ("isolation between systems").
            3. Vendor Lock-In ("dependent product architecture").
            4. Architecture by implication.
            5. Design by committee ("Swiss army knife").
            6. Reinvent the Wheel ("reinventing the wheel").

            Antipatrones de gestión de proyectos de software:
            1. Analysis paralysis.
            2. Death by planning.
            3. Corncob ("troublemakers").
            4. Irrational management.
            5. Project mismanegement.

            1 de enero de 2014


                 El principal objetivo de los patrones de diseño es guardar la experiencia de diseño de programas orientados a objetos. Cada patrón de diseño nombra, explica y evalúa un diseño importante. En otras palabras, ellos tratan de agrupar la experiencia de diseño de modo que otras personas puedan utilizarla correctamente.

                 El uso de patrones nos da la posibilidad de elegir diseños alternativos para que nuestro sistema sea reutilizable. Inclusive, nos pueden ayudar a mejorar la documentación y el mantenimiento de nuestros sistemas. En pocas palabras, los patrones de diseño nos ayuda a alcanzar mejores diseños en un tiempo más corto.

                    Aquí tienen una presentación hecha en Prezi, dónde pueden encontrar algunos conceptos básicos para entender un poco más sobre el uso de patrones de diseño.



            Subscribe to RSS Feed Follow me on Twitter!