Práctica 6 Genericidad, Patrones de Diseño Inicio: Semana del 9 de Abril. Duración: 2 semanas. Entrega: Semana del 23 de Abril (la entrega será el día de clase, según grupo, a las 23h). Peso de la práctica: 20% El objetivo de esta práctica es introducir al alumno en la creación de tipos genéricos en Java, y en la utilización de patrones de diseño en la construcción de software. La práctica consiste en una aplicación para gestionar un sistema de subastas. La aplicación subasta productos que tienen un precio de salida. Los posibles compradores muestran su interés por un producto pujando por el mismo. Cuando un usuario puja por un producto, se comunica al resto de usuarios interesados en el producto el valor de la nueva puja. Al terminar la subasta, el usuario con el valor de puja más alto es el que se lleva el pr oducto. Se pide implementar la aplicación, siguiendo los pasos que se detallan en los siguientes apartados.
Apartado 1 (7 puntos): El patrón de diseño Observer permite definir dependencias entre objetos, de manera que cuando determinado tipo de objetos cambia se los notifica a los que lo hayan solicitado. Al objeto susceptible de cambio se le llama Sujeto, mientras que a los objetos a los que se les notifica el cambio se les llama Observadores. El sistema de subastas que se pide en esta práctica es un ejemplo de aplicación del patrón Observer : al pujar por un producto su precio cambia, y como resultado se notifica el nuevo precio a todos los usuarios que anteriormente hayan pujado por el producto. De este modo, los usuarios son Observadores, y el producto es el Sujeto. En este apartado se pide implementar el sistema de subastas usando el patrón Observer . Para ello se debe comenzar creando las siguientes clases e interfaces, de las que luego haremos que hereden otras clases del sistema:
Sujeto: clase abstracta que guarda una lista de observadores (objetos de tipo Observador). Debe definir los
siguientes métodos: añadirObservador(Observador o): añade un observador a la lista. o eliminarObservador(Observador o): elimina un observador de la lista. o notificar() : notifica a todos sus observadores que ha habido cambios en el sujeto. La notificación o consiste en una llamada al método actualizar definido en los observadores (ver a continuación). Observador: interfaz de los objetos a los que se debe notificar cambios. Define el método: o actualizar(Sujeto s): debe ser implementado por las clases que quieran ser notificadas. Recibe como parámetro el objeto que ha sido modificado.
A continuación, se deben crear las clases específicas de nuestra aplicación. Se deben implementar las siguientes dos clases, así como cualquier otra clase necesaria para co mpletar el funcionamiento requerido:
Producto: tiene un código, una descripción, y un precio de salida que se irá actualizando con las sucesivas
pujas. Los cambios en el precio deben notificarse a los usuarios que antes hayan pujado por el producto; de este modo, esta clase desempeña el rol de Sujeto dentro del sistema, y debe extender la clase abstracta Sujeto. Cuando un usuario realice una nueva puja, se comprobará que la nueva puja es mayor que la última realizada, en cuyo caso se actualizará el precio del producto, y a continuación se notificará a los usuarios interesados el cambio de precio. La notificación se realizará llamando al método notificar definido en la clase padre Sujeto. Usuario: Representa un usuario del sistema, y está identificado por un nombre único. Puede pujar y desea ser notificado de cambios en el precio de los productos por los que haya pujado anteriormente; de este modo, esta clase desempeña el rol de Observador dentro del sistema, y debe implementar la interfaz Observador. El método actualizar de la clase Usuario mostrará por pantalla el nombre del usuario, así como los datos del producto cuyo precio se ha actualizado (código, descripción y precio).
La interacción con el sistema debe ser por línea de comando. El sistema debe permitir: (1) poner un nuevo producto en subasta, indicando código, descripción y un precio de salida; (2) hacer una puja por un producto, indicando código del producto, nombre de usuario y precio de puja; si la puja es válida, entonces se notificará a todos los usuarios que anteriormente hayan pujado por el mismo producto; cuando un usuario recibe la notificación de una nueva puja, mostrará por pantalla su nombre y los datos del producto por el que se pujó; (3) retirar a un usuario de la puja de un producto, indicando código del producto y nombre de usuario; a partir de entonces, el usuario no recibirá más notificaciones de las pujas realizadas por el producto. Para simplificar la implementación del sistema, un usuario puede retirarse de la puja de un producto únicamente si no es el ganador actual de la puja. (4) finalizar una puja, indicando un código de producto; los usuarios interesados serán notificados. A continuación se muestra como ejemplo un escenario de uso del sistema final:
1. 2. 3. 4.
5. 6.
crear producto P01 con descripción DESC01 y precio 100 usuario PEPE puja por producto P01 por 110 euros a. PEPE es notificado usuario LUIS puja por producto P01 por 100 euros a. puja no válida usuario LUIS puja por producto P01 por 200 euros a. PEPE es notificado b. LUIS es notificado retirar usuario PEPE finalizar puja a. LUIS es notificado
Se pide: El código Java de las clases e interfaces creadas, incluyendo el código de la aplicación de interacción con el sistema, así como el javadoc y el diagrama de clases de la aplicación.
Apartado 2 (3 puntos): Se quiere llevar un histórico de los usuarios y productos del sistema. Para evitar tener que construir una clase por cada tipo de histórico, y para facilitar la construcción de otros históricos en el futuro, se decide crear una clase genérica Histórico parametrizable con la clase cuyo histórico se desea guardar. Para poder crear un histórico de una clase, ésta debe implementar la siguiente interfaz:
interface HItem { String getIdentificador(); // devuelve el identificador del elemento String getDescripcion(); // devuelve la representación en String del elemento } Se pide implementar la clase Histórico, que debe ser un Singleton, y debe definir los siguientes métodos: (1) añadirRegistro(T ítem): añade un registro al histórico con el elemento recibido, para la fecha actual. (2) mostrar(): muestra por pantalla todos los registros del histórico, ordenados por fecha. (3) mostrar(String id): muestra por pantalla todos los registros del histórico que se refieren al elemento cuyo identificador se recibe como parámetro. Modifica la aplicación resultante del apartado 1 para poder llevar el histórico de productos del sistema. Se añadirá un registro al histórico cada vez que se cree un producto o se haga una puja por él. Como identificador del producto se utilizará su código. El histórico deberá poder imprimirse desde el menú de la aplicación. Modifica la aplicación para poder llevar el histórico de usuarios del sistema. Se añadirá un registro al histórico cada vez que un usuario haga una puja, ya sea válida o inválida. Como identificador del usuario se utilizará su nombre. El histórico deberá poder imprimirse desde el menú de la aplicación.
Se pide: El código Java de las clases e interfaces creadas, incluyendo el código de la aplicación de interacción con el sistema, así como el javadoc.
Apartado 3 (Opcional, 1 punto): Realizar una interfaz de usuario gráfica (GUI) usando swing para el sistema de subastas del apartado 1. Es suficiente con que la GUI permita sacar a subasta nuevos productos, pujar por un producto y finalizar una puja. El diseño de la GUI es libre. Una sugerencia de GUI sencilla sería una ventana con una tabla a la izquierda mostrando los productos subastados (código, descripción y precio), y a la derecha botones para cada una de las acciones.
Normas de Entrega:
Se deberán entregar los apartados 1 y 2 (y opcionalmente el apartado 3). La entrega la realizará uno de los alumnos de la pareja, a través de moodle. Se debe entregar un único fichero ZIP / RAR con todo lo solicitado, que deberá llamarse de la siguiente manera: GR_.zip. Por ejemplo Marisa y Pedro, del grupo 2261, entregarían el fichero: GR2261_MarisaPedro.zip. Los ficheros entregados deberán organizarse en distintos dir ectorios, uno por cada apartado.