domingo, 27 de octubre de 2013

Patrones de comportamiento: Chain of Responsibility, Command e Interpreter


 
Chain of Responsibility (Cadena de responsabilidad): Permite establecer la línea que deben llevar los mensajes para que los objetos realicen la tarea indicada.


     El patrón de diseño Chain of Responsibility es un patrón de comportamiento que evita acoplar el emisor de una petición a su receptor dando a más de un objeto la posibilidad de responder a una petición. Para ello, se encadenan los receptores y pasa la petición a través de la cadena hasta que es procesada por algún objeto. Este patrón es utilizado a menudo en el contexto de las interfaces gráficas de usuario donde un objeto puede contener varios objetos. Según si el ambiente de ventanas genera eventos, los objetos los manejan o los pasan.


Aplicabilidad


El patrón Cadena de Responsabilidad debe usarse cuando:

  • hay más de un objeto que puede manejar una petición, y el manejador no se conoce a priori, sino que debería determinarse automáticamente.
  • se quiere enviar una petición a un objeto entre varios sin especificar explícitamente el receptor.
  • el conjunto de objetos que pueden tratar una petición debería ser especificado dinámicamente.

  Estructura


 


  Participantes


  • Manejador: define una interfaz para tratar las peticiones. Opcionalmente, implementa el enlace al sucesor.
  • ManejadorConcreto: trata las peticiones de las que es responsable; si el ManejadorConcreto puede manejar la petición, lo hace; en caso contrario la reenvía a su sucesor.
  • Cliente: inicializa la petición a un Manejador Concreto de la cadena.


Las ventajas de este patrón son:

  • Reduce el acoplamiento. El patrón libera a un objeto de tener que saber qué otro objeto maneja una petición. Ni el receptor ni el emisor se conocen explícitamente entre ellos, y un objeto de la cadena tampoco tiene que conocer la estructura de ésta. Por lo tanto, simplifica las interconexiones entre objetos. En vez de que los objetos mantengan referencias a todos los posibles receptores, sólo tienen una única referencia a su sucesor.
  • Añade flexibilidad para asignar responsabilidades a objetos. Se pueden añadir o cambiar responsabilidades entre objetos para tratar una petición modificando la cadena de ejecución en tiempo de ejecución. Esto se puede combinar con la herencia para especializar los manejadores estáticamente.

     Por otra parte presenta el inconveniente de no garantizar la recepción. Dado que las peticiones no tienen un receptor explícito, no hay garantías de que sean manejadas. La petición puede alcanzar el final de la cadena sin haber sido procesada.


Implementación


  • Implementación de la cadena sucesora. Hay dos formas posibles de implementarla:

  1. Definir nuevos enlaces (normalmente en el Manejador, pero también podría ser en los objetos ManejadorConcreto).
  2. Usar enlaces existentes (otras asociaciones existentes). Por ejemplo, en el patrón Composición puede existir ya un enlace al padre que puede utilizarse para definir la cadena de responsabilidad sin necesidad de añadir otra asociación.

  • Conexión de los sucesores. Si no hay referencias preexistentes para definir una cadena, entonces tendremos que introducirlas nosotros mismos. En este caso, el Manejador define la interfaz y además, se encarga de mantener el sucesor. Esto permite que el manejador proporcione una implementación predeterminada de ManejarPetición que reenvíe la petición al sucesor (si hay alguno). Si una subclase de ManejadorConcreto no está intersada en dicha petición, no tiene que redefinir la operación de reenvío.

  • Representación de peticiones. Hay varias opciones para representar las peticiones:

  1. Una petición es una invocación a una operación insertada en el código. Esto resulta conveniente y seguro, pero sólo se pueden reenviar el conjunto prefijado de peticiones que define la clase Manejador.
  2. Una única función manejadora que reciba un código de petición como parámetro. Esto permite un número arbitrario de peticiones pero emisor y receptor deben ponerse de acuerdo sobre cómo codificarse la petición 



Command (Orden): Encapsula una operación en un objeto, permitiendo ejecutar dicha operación sin necesidad de conocer el contenido de la misma.
 

Intención


     Este patrón permite solicitar una operación a un objeto sin conocer realmente el contenido de esta operación, ni el receptor real de la misma. Para ello se encapsula la petición como un objeto, con lo que además se facilita la parametrización de los métodos.


Propósito


     Encapsula un mensaje como un objeto, con lo que permite gestionar colas o registro de mensaje y deshacer operaciones.

Soportar restaurar el estado a partir de un momento dado.

Ofrecer una interfaz común que permita invocar las acciones de forma uniforme y extender el sistema con nuevas acciones de forma más sencilla.


Motivo


     El concepto de "orden" puede ser ambiguo y complejo en los sistemas actuales y al mismo tiempo muy extendido: intérpretes de órdenes del sistema operativo, lenguajes de macros de paquetes ofimáticos, gestores de bases de datos, protocolos de servidores de Internet, etc.

Este patrón presenta una forma sencilla y versátil de implementar un sistema basado en comandos facilitándose su uso y ampliación.


Aplicaciones


- Facilitar la parametrización de las acciones a realizar.

- Independizar el momento de petición del de ejecución.

Implementar CallBacks, especificando que órdenes queremos que se ejecuten en ciertas situaciones de otras órdenes. Es decir, un parámetro de una orden puede ser otra orden a ejecutar.

- Soportar el "deshacer".

- Desarrollar sistemas utilizando órdenes de alto nivel que se construyen con operaciones sencillas (primitivas).


Estructura

 



Interpreter (Intérprete): Dado un lenguaje, define una gramática para dicho lenguaje, así como las herramientas necesarias para interpretarlo.

     El interpreter es un patrón de diseño que, dado un lenguaje, define una representación para su gramática junto con un intérprete del lenguaje.

     Se usa para definir un lenguaje para representar expresiones regulares que representen cadenas a buscar dentro de otras cadenas. Además, en general, para definir un lenguaje que permita representar las distintas instancias de una familia de problemas.


Motivación

      Existen problemas particulares que se pueden expresar en función de algún Lenguaje.A veces es conveniente representar un lenguaje como palabras de algún lenguaje sencillo, como por ejemplo, evaluar expresiones booleanas.

      El patrón Interpreter describe como definir una gramática, como representar palabras del lenguaje y como interpretarlas.

 

Participantes

• Cliente: Construye el árbol sintáctico abstracto de expresiones no terminales, e instancias de la clase TerminalExpresion. Luego inicializa el contexto e invoca al Interpretador.


• AbstractExpresion: Es la clase abstracta a través de la cual el cliente interactúa con las expresiones.


• TerminalExpresion: La implementación de la clase abstracta AbstractExpresion para nodos terminales en la gramática y el árbol de sintaxis.


• NonTerminalExpression: Es otra implementación de la clase abstracta para nodos no terminales de la gramática y el árbol de sintaxis. Mantiene una referencia a la siguiente expresión e invoca el método interpret en cada uno de sus hijos.


• Context: El contenedor de la información que se necesita en distintos lugares del interprete. Puede servir como un canal de comunicación entre distintas instancias de Expression.

Aplicabilidad

• Se utiliza cuando hay un lenguaje que representar cuyas sentencias se pueden representar como árboles
• La gramática es simple, de lo contrario la jerarquía de clases resulta demasiado grande y compleja
• La eficiencia no es un problema crítico
• Se obtienen soluciones más eficientes utilizando otras representaciones en lugar de árboles de análisis, como, por ejemplo, máquinas de estados (aunque éstas se pueden generar a partir de árboles construidos con este patrón)


Consecuencias

• Es fácil cambiar y ampliar la gramática.


• Resulta fácil implementarla.


• Las gramáticas complejas son difíciles de mantener.


• Añadir nuevos modos de interpretar expresiones.


Estructura

 

5 comentarios:

  1. Este patrón, recibe conjuntos de objetos.y entonces pasa cualquier solicitud de un objeto a otro hasta que se alcanza uno capaz de administrarla. El número y tipo de objetos " manejador " no es conocido en primera instancia, ya que ellos pueden ser configurados dinámicamente.

    Ejemplo :
    Existe un potencialmente variable número de "manejadores", "elementos de procesamiento" o "nodos" y una gran cantidad de peticiones que deben ser manejadas.

    ResponderEliminar
  2. la ventaja mas notable de Un patrón de diseño resulta ser una solución a un problema de diseño. y que debe ser reutilizable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.

    ResponderEliminar
  3. El patrón es utilizado a menudo en el contexto de las interfaces gráficas del usuario, hay más de un objeto que puede manejar una petición, reduce el acoplamiento. simplifica las conexionares entre objetos.

    ResponderEliminar
  4. La importancia de la reutilización de los patrones de diseño no es despreciable, ya que ésta nos provee de numerosas ventajas: reduce los esfuerzos de desarrollo y mantenimiento, mejora la seguridad informática, eficiencia y consistencia de nuestros diseños, y nos proporciona un considerable ahorro en la inversión.

    ResponderEliminar
  5. Podemos concluir que un patrón de diseño es una solución a un problema en un contexto

    ResponderEliminar