Programación en castellano
Inicio > Tutoriales > J2EE > Catálogo de Patrones de Diseño J2EE. I.- Capa de Presentación
-Tutoriales

Catálogo de Patrones de Diseño J2EE. I.- Capa de Presentación


Dispatcher View

. Contexto

El sistema controla el flujo de ejecución y accede al proceso de presentación, que es el responsable de generar el el contenido dinámico.

Nota:
El patrón Dispatcher View, igual que el patrón Service to Worker, describe una combinación común de otros patrones del catálogo. Estos dos macro-patrones describen la combinación de un controlador y un dispatcher con vistas y helpers. Aunque describen esta estructura común, cada uno enfatiza un uso diferente de los patrones.

. Problema

El problema es una combinación de los problemas resueltos por los patrones Front Controller y View Helper de la capa de presentación. No hay un componente centralizado para manejar el control de acceso, la recuperación de contenido, o el manejo de la vista, y hay código de control duplicado esparcido por varias vistas. Además, la lógica de negocio y la de formateo de la presentación están mezcladas en esas vistas, haciendo que el sistema sea menos flexible, menos reutilizable y generalmente menos resistente a los cambios.

Mezclar lógica de negocio con el procesamiento de la vista también reduce la modularidad y proporciona una pobre separación de roles entre los equipos de producción Web y de desarrollo de software.

. Causas

  • Los chequeos de autentificación y autorización se completan en cada petición.
  • El código scriptlet dentro de las vistas se debería minimizar.
  • La lógica de negocio se debería encapsular en componentes distintos a la vista.
  • El control de flujo es relativamente complejo y se basa en valores del contenido dinámico.
  • La lógica de control de la vista es relativamente sofisticada, con varias vistas que potencialmente se mapean a la misma petición.

. Solución

Combinar un controlador y un dispatcher con vistas y helpers (ver Front Controller y View Helper) para manejar peticiones de clientes y preparar una presentación dinámica como respuesta. Los controladores delegan la recuperación de contenido en los helpers, que manejan el relleno del modelo intermedio para la vista. Un dispatcher es el responsable del control de la vista y la navegación y puede encapsularse dentro de un controlador o de un componente separado.

Dispatcher View describe la combinación de los patrones Front Controller y View Helper con un componente dispatcher. Aunque este patrón y Service to Worker describen una estructura similar, ambos sugieren diferentes divisiones de la labor entre los componentes. El controlador y el dispatcher tienen responsabilidades limitadas, comparadas con el patrón Service to Worker, porque la lógica de procesamiento y de control de vista son básicas. Además, si no se considera necesario el control de los recursos subyacentes, se puede eliminar el controlador y el dispatcher se podría mover dentro de una vista.

Aunque los patrones Service to Worker y Dispatcher View representan una combinación de otros patrones del catálogo, el primero garantiza con su nombre una comunicación eficiente entre los desarrolladores. Mientras que el segundo sugiere una recuperación de contenido relegada al momento de procesamiento de la vista.

En el patrón Dispatcher View, el dispatcher normalmente juega un rol moderado en el control de la vista. En el patrón Service to Worker, el dispatcher juega un rol algo más elevado en el control de la vista.

Un rol limitado para el dispatcher ocurre cuando no se utilizan recursos exteriores para poder elegir la vista. La información encapsulada en la petición es suficiente para determinar la vista a la que despachar la petición. Por ejemplo:

http://some.server.com/servlet/Controller?next=login.jsp

La única responsabilidad del componente dispatcher en este caso es reenviar a la vista login.jsp.

Un ejemplo del dispatcher jugando un rol moderado es el caso donde el cliente envía una petición directamente al controlador con un parámetro de consulta que describe una acción a realizar:

http://some.server.com/servlet/Controller?action=login

Aquí la responsabilidad del dispatcher es traducir el nombre lógico login en el nombre del recurso de una vista apropiada, como login.jsp, y reenviar a esa vista. Para conseguir esta traducción, el dispatcher podría acceder a recursos como un fichero de configuración XML que especifica las vistas apropiadas a mostrar.

Por otro lado, en el patrón Service to Worker, el dispatcher podría invocar servicios de negocio para determinar la vista apropiada que se debe mostrar.

La estructrua compartida de Service to Worker y Dispatcher View consiste en un controlador trabajanado con un dispatcher, vistas y helpers.

. Estructura

En la siguiente figura podemos ver el diagrama de clases que representa al patrón Dispatcher View.

. Participantes y Responsabilidades

La siguiente figura muestra el diagrama de secuencia que representa al patrón Dispatcher View.

Aunque las responsabilidades del controlador están limitadas a los servicios del sistema, como la autentificación y autorización, todavía es beneficioso centralizar estos aspectos del sistema. Observa también que, al contrario que el patrón Service to Worker, el dispatcher no hace llamadas a servicios de negocio para poder completar el procesamiento de la vista.

La funcionalidad del dispatcer se podría encapsular en su propio componente. Al mismo tiempo, cuando las responsabilidades del dispatcher son limitadas, como se describen en este patrón, la funcionalidad del dispatcher se puede poner en otro componente, como en el controlador o la vista.

De hecho, la funcionalidad del dispatcher podría incluso ser completada por el contenedor, en el caso donde no sea necesaria una lógica extra a nivel de la aplicación. Un ejemplo es una vista llamada main.jsp a la que se le da el alias de first. El contenedor procesará la siguiente petición, traduciendo el nombre del alias al nombre del recurso físico, y reenviando directamente a ese recurso:

http://some.server.com/first --> /mywebapp/main.jsp

En este caso, nos hemos quedado con el patrón View Helper, donde la petición la maneja directamente la vista. Como la vista es el punto de contacto inicial para manejar peticiones, normalmente se utilizan etiquetas personalizadas para realizar el procesamiento de negocio o para delegar este procesamiento a otros componentes.

Así, el patrón Dispatcher View describe una continuidad de escenarios relacionados, moviéndose de un escenario que es estructuralmente similar a Service to Worker a otro que es similar a View Helper.

. Controller

El controlador normalmente es el punto de contacto inicial para manejar una petición. El controlador maneja la autentificación y la autorización, y delega en un dispatcher para hacer el control de la vista.

. Dispatcher

Un dispatcher es el responsable del control de la vista y la navegación, controlando la elección de la siguiente vista a mostrar y proporciona el mecanismo para dirigir el control a este recurso.

Un dispatcher se puede encapsular dentro de un controlador (ver Front Controller) o puede ser un componente independiente que trabaja en coordinación con el controlador. El dispatcher puede proporcionar reenvío estático a la vista o podría proporcionar un mecanismo de reenvío dinámico más sofisticado.

. View

Una Vista representa una presentación de información al cliente. La información utilizada en esta presentación se recupera de un modelo. Los helpers soportan vistas encapsulando y adaptando un modelo para utilizarlo en una presentación.

. Helper

Un helper es el responsable de ayudar a la vista o al controlador a completar su procesamiento. Así, los helpers tienen numerosas responsabilidades, incluyendo la obtención de los datos requeridos por la vista y almacenándolos en el modelo intermedio, en cuyo caso el helper es conocido como un value bean. Además, los helpers podrían adaptar este modelo de datos para que los utilice la vista. Los helpers pueden servir peticiones de datos desde la vista simplemente proporcionando acceso a los datos en bruto o formateándolos como contenido Web.

Una vista podría trabajar con cualquier número de helpers, que normalmente están implementados por componentes JavaBeans (JSP 1.0+) o componentes de etiquetas personalidas (JSP 1.1+). Además, un helper podría representar un objeto Command o delegate.

. ValueBean

Un value bean es otro nombre para un helper que es responsable de contener el estado del modelo intermedio para que lo utilice una vista.

. BusinessService

Servicio de Negocio es un rol que cumple el servicio al que el cliente quiere acceder. Normalmente, se accede al servicio de negocio mediante un Business delegate. El rol del business delegate es proporcionar control y protección para el servicio de negocio (puedes ver el patrón "Business Delegate" más adelante).

. Estrategias

. Servlet Front

Ver la estrategia "Servlet Front" en el patrón Front Controller.

. JSP Front

Ver la estrategia "JSP Front" en el patrón Front Controller.

. JSP page View

Ver la estrategia "JSP page View" en el patrón View Helper.

. Servlet View

Ver la estrategia "Servlet View" en el patrón View Helper.

. JavaBean Helper

Ver la estrategia "JavaBean Helper" en el patrón View Helper.

. Custom Tag Helper

Ver la estrategia "Custom Tag Helper" en el patrón View Helper.

. Dispatcher in Controller

Ver la estrategia "Dispatcher en Controller" en el patrón Front Controller.

Como hemos visto, los patrones Service to Worker y Dispatcher View sugieren una continuidad, donde el comportamiento se ha encapsulado más cerca de la vista o se ha movido hacía atrás en el flujo de proceso. La siguiente figura muestra las interacciones para esta estrategia:

El controlador no crea explicitámente un objeto dispatcher. En vez de eso, el controlar tiene cuidado de reenviar a la vista. Alternativamente, se podría implementar un dispatcher en el que el controldor puede delegar la función de reenvío.

. Dispatcher in View

Si el controlador se eliminara debido a su rol limitado, el dispatcher se podría mover a una vista. Este diseño puede ser útil en casos donde es típico que una vista mapee a una petición específica, pero donde se podría utilizar de forma poco frecuente un vista secundaria. Por ejemplo, basándose en la información de la petición o los resultados de algún procesamiento de la vista, un helper de etiqueta personalizada en la vista podría dirigir el control a una vista secundaria. Un caso típico es cuando una petición de cliente es reenviada a una vista específica, y será servida por esa vista en cualquier otro caso.

Consideremos el caso donde el usuario no se ha autentificado, pero pide acceso a unas páginas JSP protegidas de la site. Como la site tiene sólo unas pocas páginas JSP protegidas, y el contenido dinámico es limitado, la autentificación se puede realizar dentro de esas páginas JSP, en lugar de utilizar un controlador centralizado para toda la site. Esas páginas que necesitan autentificacion incluyen un helper de etiqueta personalizada al principio de la página. Este helper realiza el chequeo de autentificación y muestra la página al usuario o lo reenvía a la página de autentificación. La siguiente figura representa este escenario:

. Transformer Helper

Ver la estrategia "Transformer Helper" en el patrón View Helper.

. Consecuencias

  • Centraliza el Control y Mejora la Modularidad y la Reutilización
    Este patrón sugiere proporcionar un lugar central para manejar los servicios del sistema y la lógica de negocio entre varias peticiones. El contolador maneja el procesamiento de la lógica de negocio y el manejo de peticiones. Hay que tener en cuenta, que como control centralizado, es posible introducir un sólo unto de fallo.
  • Mejora el Particionamiento de la Aplicación
    La utilización de helpers resulta en una separación clara entre la vista y el procesamiento de negocio en una aplicación. Los helpers, en la forma de JavaBeans (JSP 1.0+) o etiquetas personalizadas (JSP 1.1+), proporcionan un lugar donde construir la lógica de negocio fuera de la página JSP. Si la lógica de negocio se deja dentro de la página JSP, los grandes proyectos resultan embrollados.
  • Mejora la Separación de Roles
    Al separar la lógica de formateo de la lógica de negocio de la aplicación también se reducen las dependencias de los mismos recursos entre individuos que cumplen diferentes roles. Sin esta separación, por ejemplo, un desarrollador de sofware poseería código que está embebido dentro de marcas HTML, mientras que un miembro del equipo de producción Web necesitaría modificar la distribución de una página y diseñar componentes que están mezclados con lógica de negocio. Como ningún individuo que cumple estos roles está familiarizado con las implementaciones específicas del trabajo del otro individuo, se puede llegar a un punto de confusión en que las modificaciones accidentales introduzcan errores el sistema.

. Código de Ejemplo

El siguiente código de ejemplo muestra una implementación del patrón Dispatcher View, utilizando un servlet controlador y una vista con helpers JavaBean y de etiquetas personalizadas. La implementación incluye las estrategias Servlet Front, Dispatcher in Controller, JSP View, JavaBean Helper y Custom Tag Helper. También utiliza una vista compuesta muy básica, mostrada en la siguiente imagen:

El siguiente ejemplo muestra el servlet controlador que simplemente completa el chequeo de autentificación y pasa el control a la vista apropiada. Observa que el controlador no delega directamente a ningún componente helper para poder hacer llamadas a la capa de negocio mediante Delegate. Estás responsabilidades se han relegado a la vista, que se llama accountdetails.jsp. El código de ejemplo utiliza un LogManager para guardar los mensajes.


public class Controller extends HttpServlet {

  /** Processes requests for both HTTP 
    * <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
  protected void processRequest(HttpServletRequest 
    request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
    String nextview;
    try {
      LogManager.recordStrategy(request, 
        "Dispatcher View", 
        " Servlet Front Strategy; " + 
    "JSP View Strategy; Custom tag helper Strategy");
      LogManager.logMessage(request, getSignature(), 
        "Process incoming request. ");

      // Use a helper object to gather parameter 
      // specific information.
      RequestHelper helper = new 
          RequestHelper(request, response);
      LogManager.logMessage(request, 
        getSignature(), " Authenticate user");

      Authenticator auth = new BasicAuthenticator();
      auth.authenticate(helper);

      //This is an oversimplification for the sake of 
      // simplicity. Typically, there will be a 
      // mapping from logical name to resource name at 
      // this point
      LogManager.logMessage(request, getSignature(), 
        "Getting nextview");
      nextview = request.getParameter("nextview");

      LogManager.logMessage(request, getSignature(), 
        "Dispatching to view: " + nextview);
    }
    catch (Exception e) {
      LogManager.logMessage(
        "Handle exception appropriately", 
        e.getMessage() );
      /** ApplicationResources provides a simple API 
        * for retrieving constants and other 
        * preconfigured values**/
      nextview = ApplicationResources.getInstance().
          getErrorPage(e);
    }
    dispatch(request, response, nextview);
  }

  /** Handles the HTTP <code>GET</code> method.
    * @param request servlet request
    * @param response servlet response
    */
  protected void doGet(HttpServletRequest request, 
    HttpServletResponse response)
  throws ServletException, java.io.IOException {
    processRequest(request, response);
 }

  /** Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
  protected void doPost(HttpServletRequest request, 
    HttpServletResponse response)
  throws ServletException, java.io.IOException {
    processRequest(request, response);
  }

  /** Returns a short description of the servlet. */
  public String getServletInfo(){
      return getSignature();
  }

  public void init(ServletConfig config) throws 
    ServletException {
    super.init(config);
  }

  public void destroy() { }

  /**
    * dispatcher method
    */
  protected void dispatch(HttpServletRequest request,
    HttpServletResponse response, String page) 
    throws javax.servlet.ServletException, 
    java.io.IOException {
        RequestDispatcher dispatcher = 
          getServletContext(). 
            getRequestDispatcher(page);
        dispatcher.forward(request, response);
  }

  private String getSignature()  {
    return "DispatcherView-Controller"; 
  }
}

Observa que la vista utiliza helpers de etiquetas personalizadas para controlar la recuperación de contenido. ya que esta actividad no se realizó en el controlador. Cuando se utilizan las etiquetas personalizadas de esta forma, normalmente se convierten en estrechas fachadas para componentes solitarios en los que delegar para completar este procesamiento. De esta forma, la lógica de procesamiento general está pobremente acoplada a la implementación de la etiqueta. Si no se utilizan etiquetas personalizadas con Dispatcher View, la página JSP se terminará llenando de códgio scriptlet, una situación que debemos evitar.

 

<%@ taglib uri="/web-INF/corepatternstaglibrary.tld"
  prefix="corepatterns" %>

<html>
<head><title>AccountDetails</title></head>
<body>

<corepatterns:AccountQuery 
  queryParams="custid,acctkey" scope="request" />

<h2><center> Account Detail for <corepatterns:Account
  attribute="owner" /></h2> <br><br>

<tr>
  <td>Account Number :</td>
  <td><corepatterns:Account attribute="number" /></td>
</tr>

<tr>
  <td>Account Type:</td>
  <td><corepatterns:Account attribute="type" /></td>
</tr>

<tr>
  <td>Account Balance:</td>
  <td><corepatterns:Account attribute="balance" /></td>
</tr>

<tr>
 <td>OverDraft Limit:</td>
 <td><corepatterns:Account attribute="overdraftLimit" /></td>
</tr>
<table border=3>
</table>
</corepatterns:AccountQuery>

<br>
<br>

</center>
<%@ include file="/jsp/trace.jsp" %>
</body>
</html>

. Patrones Relacionados

  • Front Controller y View Helper
    El patrón Dispatcher View es el resultado de combinar el patrón View Helper con un dispatcher, en coordinación con el patrón Front Controller.
  • Service to Worker
    El patrón Service to Worker es otro nombre para la combinación del patrón Front Controller con un dispatcher, y el patrón View Helper. Los patrones Service to Worker y Dispatcher View son idénticos con respecto a los componentes implicados, pero son diferentes en la división de labores entre esos componentes. El patrón Dispatcher View siguiere relegar la recuperación de contenido al momento en que se procesa la vista. Además, el dispatcher juega un rol más limitado en el control de la vista, ya que la elección de le vista normalmente ya está incluida en la petición.
 
Patrocinados
 

Copyright © 1999-2007 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network

red internet: musica mp3 | logos y melodias | hospedaje web linux | registro de dominios | servidores dedicados
más internet: comprar | recursos gratis | posicionamiento en buscadores | tienda virtual | gifs animados