El
“Interceptor” es un patrón arquitectónico que permite la inclusión de nuevos
servicios a un marco de trabajo de forma transparente para las aplicaciones y el
sistema. Estos servicios se activan automáticamente cuando ocurren determinados
eventos.
En este ejercicio se trata de aplicar el patrón anterior al desarrollo de un
patrón “Interceptor de Filtros” (mezcla entre el estilo arquitectónico
“Filtros-encauzamientos” y el patrón arquitectónico aludido). El “Interceptor de
Filtros” se utiliza cuando queremos hacer algún “pre-procesado” y
“post-procesado” como enviar una petición o recibir respuesta de una aplicación,
respectivamente. Los filtros se programan y se utilizan cuando se produce la
petición y antes de pasar tal petición a la aplicación “objetivo” que tiene que
procesarla.
Los filtros pueden realizar la autenticación/autorización/conexión(loggin)
o trazar la petición antes de pasarla a los objetos gestores que van a
procesarla.
A continuación se pueden ver las entidades de modelado necesarias para programar
el patrón “Interceptor de Filtros”:
Filtro: Filtro que realizará cierta tarea antes o después de la
ejecución de la petición por el objeto gestor demandado.
CadenaFiltros: Cadena de filtros que proporciona varios filtros al
GestorFiltros y los ejecuta en orden en que fueron introducidos en la
aplicación.
Objetivo: Es el objeto que se encarga de gestionar la petición que
se envía desde el cliente.
GestorFiltros: Se encarga de gestionar los filtros( crea la cadena
de filtros y tiene métodos para añadir filtros concreto y que se ejecute la
petición por los filtros y el “objetivo”).
Cliente: Es el objeto que envía la petición a la instancia de
Objetivo.
2. Trabajo a realizar
Vamos a crear clases CadenaFiltros, GestorFiltros, Objetivo y Cliente. También varios objetos que representen tales entidades de modelado en nuestra aplicación de demostración. “Filtro1” y “Filtro2” representarán a los filtros concretos, que pueden realizar alguna de las siguientes tareas: autenticación, seguimiento, loggin de la petición. Programar una clase que incluya un main() y que utilice a un objeto Cliente para demostrar el funcionamiento del patrón “Interceptor de Filtros”. Ver el diagrama de secuencia:
Se trata de aplicar el patrón reflection para re-implementar alguno de los ejemplos ya programados con el patrón “factoría abstracta” de forma que el código de las factorías tenga un comportamiento reflexivo. Para programarlo se pueden utilizar las facilidades que ofrece JDK 2.0 y JDK 3.0:
-Cargar dinámicamente una clase: Class c= Class.forName(“NombreClase”);
-Determinar si se trata de una clase o de una interfaz: c.isInterface();
-Determinar su superclase y las interfaces que ha implementado: Class c1= c.getSuperclass(); | Class[] c2= c.getInterfaces();
-Obtener una nueva instancia de una clase: Object o1= c.newInstance();
Constructor c1= c.getConstructor(Class[]{…}); Object o1= c1.newInstance(Object[]{…})
(se pueden conseguir también todos los constructors declarados con getDeclaredConstructors())
-Determinar métodos de instancia y de clase: Methods[] m1= c.getDeclaredMethods(); Method m= c.getMethod(“Nombre de método”, new Class[]{…});
-Llamar a los métodos de instancia y de clase: m.invoke(c.new Object[]{…});
-Determinar modificadores de campos, métodos, clases e interfaces: Modifiers[] mo= c.getModifiers();
-Obtener los campos declarados en clases: Class[] f= c.getDeclaredFields(); Field f= c.getField();
-Obtener el valor de un campo específico de un objeto: f.get(o);
-Modificarlo: f.set(o,valor);
Por ejemplo, para programar una “factoría de objetos gráficos”,
Lista s= new ArrayList();
s.add(new Circulo());
s.add(new Cuadrado());
s.add(new Triangulo());
for(Iterator e= s.iterator; e.hasNext();)
((Forma) e.next()).dibujar();
Con el patrón “Factoría Abstracta” no-reflexivo, programaríamos como se indica el siguiente código:
public static Forma crearForma(String s){
Forma temp= null;
If (s.equals(“Circulo”)) temp= new Circulo();
else If (s.equals(“Cuadrado”)) temp= new Cuadrado();
else If (s.equals(“Triangulo”)) temp= new Triangulo();
else System.out.printl(“ERROR!!!”);
return temp;
}
Pero el método crearForma(String s) lo podemos convertir en “reflexivo” si en lugar del código anterior programamos lo que sigue:
public static Forma crearForma(String s){
Forma temp= null;
try {
temp= (Forma) Class.forName(s).newInstance();
}
Catch (Exception e) { }
return temp;
}
Suponer que vamos a diseñar una red innovadora para la automatización de una casa (aplicación de domótica) donde la red central permite conectar distintos dispositivos de tipo actuador y sensor. La red ha de ser capaz de integrar dispositivos heterogéneos tales como VCRs, TVs, tabletas, móviles, refrigeradores, alumbrado, congeladores, o sensores de seguridad. Proporcionará una determinada conectividad entre todos los elementos a través de algunos cables y conexiones WIFI (varias de ellas). El acceso externo al sistema “E-Home” será posible sólo a través de un acceso a Internet seguro. El control central y de servicios del sistema pueden ayudar a monitorizar y modificar el comportamiento del sistema o su mal funcionamiento. Los usuarios y administradores podrían instalar servicios a medida que soporten a múltiples dispositivos para permitir nuevos comportamientos del entorno o del sistema, tales como: activación de eventos en un dispositivo como consecuencia de la existencia de otros eventos. Ejemplos de esto pueden ser, grabar una emisión de televisión activada por un reloj central o la activación del sistema de aire acondicionado por medio de una llamada telefónica. Tales servicios serán implementados por los distintos vendedores de dispositivos que puedan ser de utilidad para E-Home.
Para hacer posible la funcionalidad anteriormente descrita para el sistema E-Home, todos los servicios han de colaborar. Aunque los servicios que están situados en varios controladores repartidos por la casa estarán conectados a través de una red con el software que se ejecuta en los dispositivos. Ha de ser posible cambiar las colaboraciones entre dispositivos con facilidad y los servicios no tienen por qué ejecutarse siempre en el mismo controlador. Para que tal red de dispositivos domésticos colaborativos tenga éxito es necesario facilitar a los vendedores el que puedan crear nuevos servicios de manera ágil sin que sea necesario invertir demasiado tiempo aprendiendo cómo desarrollar software para esta red.
El diagrama de secuencia que podría representar las interacciones entre los componentes de una arquitectura-solución de acuerdo con el patrón Broker:
Las dependencias entre los participantes en el citado patrón: