Patrones de diseño

Entre hoy y ayer en el trabajo he estado utilizando el patrón de diseño Visitor. Es mi primer encuentro directo con un patrón de la banda de los cuatro (GoF o Gang of Four), y mira que estuve pensando la solución un buen rato hasta que mi jefe me contó lo del patrón en cuestión, que explicaré brevemente a continuación.

El patron Visitor se utiliza cuando existe una clase padre A y una o varias clases hijas A1, A2, …, AN; todas tienen un metodo comun, por ejemplo metodo1() que realiza diferentes tareas dependiendo del tipo de la clase. ¿Para quá puede servir esto? Pues para iterar por una lista de clases A e hijas y llamar al metodo1 en cada clase.
El problema surge en que para recorrer la lista, el tipo del objeto (item) en cada iteracion debe ser de tipo A (el padre), y que si se llama a item.metodo1() ¡se ejecutara el metodo1 contenido en la clase padre! En lugar de lo correcto, que serí­a ejecutar el metodo1 de la clase hija a la que pertenezca el item.

La solucion consiste en crear un metodo accept(VisitanteA visitante) en todas las clases A e hijas que acepte un “visitante” (una clase de tipo VisitanteA). En el metodo accept se llama al método visit de la clase visitante que se paso como parametro, y el unico parametro del método visit es “this”, un puntero al objeto actual.

En la clase VisitanteA se implementa un método visit(A param), otro visit(A1 param), otro visit(A2, param), etc. Uno por cada clase que se quiera “visitar”. En ese método visit(Ax param) es dónde se ejecuta la lógica de nuestro antiguo método1(). De este modo, el Visitante “descubre” la clase del objeto, ya que el objeto se enví­a a si mismo y debido a la sobrecarga del método visit() se ejecutan las sentencias correctas.

Espero haberlo explicado medianamente bien. Por el momento he implementado como 4 o 5 clases visitantes. Tengo muchas herencias inusuales y restricciones semánticas en la base de datos que requieren del patrón. Todo esto me pasa por “mover” el modelo a la base de datos, en lugar de implementarlo en la lógica de negocio. Sin embargo, considero que este enfoque es mejor y más mantenible, aunque más laborioso. En fin, veremos como acaba el proyecto.

Posted By dsuarez

David nació en Las Palmas de Gran Canaria, España. Estudió Ingeniería en Informática en la Universidad de Las Palmas de Gran Canaria (ULPGC), donde ha trabajado en investigación los últimos años. Siempre ha sentido una gran curiosidad por los ordenadores y las ciencias, y más recientemente en el mundo empresarial. Ha trabajado como programador/analista, consultor en tecnologías de la información y obtuvo la beca de Google Summer of Code en 2006. Es socio fundador de Wantudu (http://wantudu.es), empresa especializada en terminales táctiles para hoteles.

One Response to “Patrones de diseño”

  1. jorge says:

    tí­o, soy jorge, pillate el libro de los gof sin falta y enchufatelo. Está muy bien escrito y te hace pensar mejor

  2. Juan says:

    Hola!

    Esto es muy viejo ya pero tení­a que comentarte. El patrón visitor está bien pero esto que dices:

    El problema surge en que para recorrer la lista, el tipo del objeto (item) en cada iteracion debe ser de tipo A (el padre), y que si se llama a item.metodo1() ¡se ejecutara el metodo1 contenido en la clase padre! En lugar de lo correcto, que serí­a ejecutar el metodo1 de la clase hija a la que pertenezca el item.

    ES TOTALMENTE ERRONEO! El método a ejecuta se determina en tiempo de ejecución según el tipo dinámico del objeto … No se ejecuta el método del tipo base.

    Esto es una de las bases de la POO, así­ que me parecí­a importante comentartelo.

  3. Juan says:

    Diré así­ como nota que el problema del que querrí­as hablar es el “double dispatch” , cuando quieres que metodo1() acepte distintos objetos lease:

    int metodo1(TipoPadre)
    int metodo1(TipoHijo)

    ya que solo se comprueba el tipo estático , lease: si tienes una referencia del tipo TipoPadre que está apuntando a un TipoHijo cuando ejecutes metodo1(referencia) se comprueba el tipo estático -> es una referencia a TipoPadre asi que se ejecuta metodo1(TipoPadre) sin comprobar dinámicante que realmente el objeto es del tipo TipoHijo

Leave a Reply