viernes, 19 de junio de 2015

Patrones de diseño: Chain of Responsability e Interpreter

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.

Se utiliza cuando:
-Las peticiones emitidas por un objeto deben ser atendidas por distintos objetos receptores
-No se sabe a priori cual es el objeto que me puede resolver el problema
-Cuando un pedido debe ser manejado por varios objetos
-El conjunto de objetos que pueden tratar una petición debería ser especificado dinámicamente

La motivación detrás de este patrón es crear un sistema que pueda servir a diversas solicitudes de manera jerárquica. En otras palabras, si un objeto que es parte de un sistema no sabe cómo responder a una solicitud, la pasa a lo largo del árbol de objetos. Como el nombre lo implica, cada objeto de dicho árbol puede tomar la responsabilidad y atender la solicitud.
Un ejemplo típico podría ser el lanzar un trabajo de impresión. El cliente no sabe siquiera qué impresoras están instaladas en el sistema, simplemente lanza el trabajo a la cadena de objetos que representan a las impresoras. Cada uno de ellos lo deja pasar, hasta que alguno, finalmente lo ejecuta.

Hay un desacoplamiento evidente entre el objeto que lanza el trabajo (el cliente) y el que lo realiza (impresora). 

Ejemplo

Escenario: estamos realizando el software para un banco y uno de los puntos más importantes es saber quién puede aprobar un crédito. Por lo tanto el banco define las siguientes reglas de negocio:

Si el monto no supera los $ 10.000 entonces el ejecutivo de cuenta pueda aprobar el préstamo.
Si el monto esta entre los $10.000 y $50.000 entonces la persona indicada para realizar la aprobación es el líder inmediato de dicho ejecutivo.
Si el monto se encuentra entre $ 50.000 y $100.000 entonces es el Gerente quién debe realizar dicha aprobación.
Por montos superiores a los $100.000 entonces la aprobación la realizará el Director.

Para este caso se ha decidido realizar un patrón Chain of Responsibility. Se decide crear una interface llamada IAprobador que debe implementar toda clase que pertenezca a nuestra cadena de responsabilidades.








En nuestro caso será el banco quién organice la cadena, pero seguramente en la práctica utilizaremos un factory. Para el cliente el banco será su punto de entrada.


Y, desde el punto de vista del cliente, verán que es muy sencillo:




Interpreter

Este patrón busca representar un lenguaje mediante reglas gramáticas. Para ello define estas reglas gramáticas y como interpretarlas. Utiliza una clase para representar una regla gramática.
Si un tipo particular de problema se presenta frecuentemente, puede ser provechoso expresar los diferentes casos del problema como sentencias de un lenguaje simple. Se puede, entonces, construir un intérprete que resuelva el problema interpretando dichas sentencias.

Cuando Utilizarlo.

Este patrón se debe utilizar cuando hay un lenguaje que interpretar y se puede interpretar sus palabras como árboles sintácticos abstractos. Para ello, la gramática debe ser simple.
Difícilmente el desarrollador utilice este patrón en algún momento de su vida, lo que no quita que no sea un patrón utilizado. La situación ideal que se debe considerar para aplicar este patrón es que exista un lenguaje sencillo que pueda interpretarse con palabras. El ejemplo más claro es JAVA: este lenguaje permite escribir en archivos .java entendibles por humanos y luego este archivo es compilado e interpretado para que pueda ejecutar sentencias entendibles por una máquina.

Ejemplo

Luego de leer el ejemplo, se entenderá porque este patrón sólo funciona con lenguajes con reglas sencillas... de hecho este ejemplo no lo pensé yo, lo vi en una página hace muchos años y no recuerdo cual era para colocar la fuente...
Veamos un ejemplo donde se utiliza el interpreter para interpretar los números romanos mediante ciertas reglas matemáticas y convertirlo en un número de escala decimal.

Primero creamos el contexto: esto es una clase donde tiene un input (un String ya que los numeros romanos son letras) y un output (un int ya que la respuesta será un número).

Lo que sigue a continuación es puro algoritmo: si pensamos como funcionan los numeros romanos vamos a encontrar un patrón (pongo como ejemplo con escala de 10 pero es lo mismo para el resto de las escalas): de 1 a 3 es el mismo signo I (ocupa 1 espacio por vez), el 4 es una combinacion del 5 con el 1.... IV (ocupan dos lugares), el 5 es V (ocupa 1 lugar) y el próximo signo que hace combinación es el 9 (IX) que utiliza un signo de una escala mayor.
 Una vez que entendemos el algoritmo y logramos la interpretación correcta, agregar una nueva expresión es muy sencillo. Aca corte en 1000 porque ya se entiende la idea.
Veremos esto en practica:

No hay comentarios:

Publicar un comentario