OBJETIVOS FUNDAMENTOS DE PROGRAMACIÓN Curso: 2011/12 BOLETÍN DE PROBLEMAS 15: FACTORÍAS E ITERABLES Versión: 1.0.2 Aprender a crear factorías para gestionar la creación de objetos en Java. Aprender a utilizar las factorías como gestores de propiedades compartidas. Aprender a implementar tipos iterables y, en especial, iterables virtuales. EJERCICIO 0.1: SECUENCIA ARITMÉTICA Cree una clase denominada SecuenciaAritmetica que implemente Iterable<Double>. Dicha clase debe tener un constructor que tome tres valores: valor inicial, valor final y diferencia. En cada iteración, el objeto devolverá un valor de la secuencia entre valor inicial y final inclusive. El valor actual será en todo caso el valor anterior más la diferencia definida en el constructor. Así, por ejemplo, para el objeto SecuenciaAritmética(3,10,2) tendremos como salida los valores 3,5,7,9. EJERCICIO 0.2: SECUENCIA GEOMÉTRICA De manera análoga al ejercicio anterior, defina un nuevo tipo denominado SecuenciaGeometrica que en cada iteración, devuelva un valor de la secuencia geométrica entre dos valores dados, con un valor de razón determinado. Así, por ejemplo, para el objeto SecuenciaGeometrica(1.0, 1000.0, 5.0) tendremos como salida los valores 1.0, 5.0, 25.0, 125.0, 625.0. EJERCICIO 0.3: SECUENCIA FIBONACCI En este ejercicio abordaremos la creación de un tipo SecuenciaFibonacci. Este tipo debe devolver la sucesión de Fibonacci: 1, 1, 2, 3, 5,, hasta un valor concreto que se pasa como parámetro al constructor. Tenga en cuenta que el nuevo tipo es un iterable virtual y recuerde que cada valor se calcula sumando los valores de los dos anteriores (v0=1, v1=1, v n =v n-1 + v n-2, tal que n>1). EJERCICIO 0.4: SECUENCIA DE DÍGITOS En este ejercicio, queremos definir otro iterable virtual denominado SecuenciaDigito que sea capaz de iterar por los distintos dígitos de un número entero (tipo Long) en base decimal. Para ello, tenga en cuenta que para calcular el dígito en cada posición, debemos extraer su valor mediante la operación módulo del valor actual y el valor base (en nuestro caso 10). Posteriormente, debemos actualizar el valor actual para que en la siguiente iteración se devuelva el siguiente dígito. Por ejemplo, el objeto creado mediante SecuenciaDigitos(568427), devolvería los valores 7,2,4,8,6,5. Nota: Piense cómo generalizar esta solución para que pueda trabajar con cualquier base.
Boletín de problemas 15: Factorías e Iterables 2 EJERCICIO 0.5: SECUENCIA DE NÚMEROS PRIMOS Para terminar con los ejercicios de esta primera parte del boletín, realice un último iterable virtual llamado SecuenciaPrimo que recorra la secuencia de números primos entre dos valores que se pasan como parámetros en el constructor. Apóyese en la clase de utilidades Enteros y en concreto, en el método esprimo. Un ejemplo de uso de este iterable virtual podría ser el objeto construido con la llamada SecuenciaPrimo(11) que devolvería la secuencia 1,2,3,5,7,11. EJERCICIO 1: FACTORÍA DE CONJUNTOS Cree una factoría denominada Conjuntos para generar objetos de tipo Set. Tenga en cuenta que la clase conjuntos podrá generar objetos de tipo HashSet o también de tipo LinkedHashSet. Investigue el API de java y genere métodos estáticos para cada uno de los constructores válidos de dichos tipos. EJERCICIO 2: CADENA ITERABLE BIDIRECCIONAL Se desea construir un tipo que permita recorrer los caracteres de una cadena de izquierda a derecha y viceversa. Para ello, se pide implementar un nuevo tipo denominado CadenaIterableBidireccional que extiende a Iterable y que sólo tiene una propiedad consultable de tipo String, denominada cadena, y la propiedad tiporecorrido de tipo TipoRecorrido, consultable y modificable. Tenga en cuenta que el criterio de igualdad será el de la cadena y este tipo no será copiable. NOTA: No reutilice ArrayBidireccional. Cree los iteradores necesarios apoyándose en los métodos length y charat de String. EJERCICIO 3: CADENA BIDIRECCIONAL SOBRE ARRAY BIDIRECCIONAL Realice ahora el ejercicio anterior pero proponga una nueva implementación que reutilice por composición el tipo ArrayBidireccional. EJERCICIO 4: SECUENCIA DE FECHAS En este ejercicio vamos a crear un iterable virtual. En concreto, vamos a crear un tipo nuevo denominado SecuenciaFecha que va a generar un conjunto de fechas válido entre dos fechas dadas, ambas inclusive. Para ello, tenga en cuenta que: En la clase Fechas, defina un método esfechavalida que devuelva true si la fecha que se le pasa es correcta. Para ello, reutilice el método getnumerodiasmes visto en la primera parte de la asignatura. Si alguna de las fechas iniciales no es válida, se debe lanzar una excepción. Si la fecha inicial es posterior a la final, se debe lanzar una excepción. El iterador privado deberá guardar en una propiedad el valor de la siguiente fecha válida. Dicha fecha se actualizará cada vez que se invoque al método next del iterador.
Boletín de problemas 15: Factorías e Iterables 3 Para realizar la búsqueda implemente un método privado denominado nextfechavalida y delegue en él dicha responsabilidad. EJERCICIO 5: SECUENCIA DE CAPTCHAS En este ejercicio vamos a implementar una secuencia de Captchas. Un Captcha es una prueba o test que se utiliza para determinar cuándo un usuario es humano o no. Una forma de implementar un Captcha es a través de una imagen que contiene un texto con algún tipo de ruido de forma que pueda ser leído por un humano pero no por un ordenador (OCR, Reconocimiento Óptico de Caracteres). Por ejemplo, en la siguiente imagen se puede leer la cadena bxdcha : Para implementar un captcha se proporciona la siguiente clase: public class CaptchaImpl { private static final Integer MAX_LONG = 10; private static final Integer MAX_WIDTH = 300; private static final Integer MAX_HEIGHT = 300; private static final Integer DEFAULT_WIDTH = 250; private static final Integer DEFAULT_HEIGHT = 90; private String value; private String filename; private Integer width, height; private Random trnd = new Random(); public String getvalue() { return value; public void setvalue(string value) { if (value.length() <=0 value.length() >= MAX_LONG) throw new IllegalArgumentException("Catpcha. setvalue: longitud de cadena no comprendida entre 0.."+MAX_LONG); this.value = value; public String getfilename() { return filename; public void setfilename(string fn) { this.filename = fn; public Integer getwidth() { return width; public void setwidth(integer w) { if (w < 0 w > MAX_WIDTH) throw new IllegalArgumentException("Catpcha.setWidth: valor no comprendido entre 0.." + MAX_WIDTH); this.width = w;
Boletín de problemas 15: Factorías e Iterables 4 public Integer getheight() { return height; public void setheight(integer h) { if (h < 0 h > MAX_HEIGHT) throw new IllegalArgumentException("Catpcha.setHeight: valor no comprendido entre 0.." + MAX_HEIGHT); this.height = h; public CaptchaImpl(String value) { setvalue(value); setfilename(value + ".jpg"); setwidth(250); setheight(90); public CaptchaImpl(String value, String filename) { setvalue(value); setfilename(filename); setwidth(default_width); setheight(default_height); public CaptchaImpl(String value,string filename,integer width,integer height){ setvalue(value); setfilename(filename); setwidth(width); setheight(height); public void createjpg() { Color back = new Color(255, 255, 255); Color cfont = new Color(0, 0, 255); Font tfont = new Font("SansSerif", 1, 25); BufferedImage bufimage = new BufferedImage(getWidth(), getheight(), BufferedImage.TYPE_INT_RGB); Graphics g = bufimage.creategraphics(); g.setcolor(back); g.fillrect(0, 0, getwidth(), getheight()); g.setcolor(cfont); for (int i = 0; i < 15; i++) // Generamos algo de ruido aditivo g.drawline(trnd.nextint(getwidth()), trnd.nextint(getheight()), trnd.nextint(getwidth()), rnd.nextint(getheight())); g.setcolor(cfont); g.setfont(tfont); g.drawstring(getvalue(), getwidth() / 4, getheight() / 2); g.setcolor(back); for (int i = 0; i < 20; i++) // Generamos algo de ruido substractivo g.drawline(trnd.nextint(getwidth()),trnd.nextint(getheight()), trnd.nextint(getwidth()), trnd.nextint(getheight())); File file = new File(getFilename()); try { file.createnewfile(); ImageIO.write(bufImage, "jpg", file); catch (IOException oops) { oops.printstacktrace();
Boletín de problemas 15: Factorías e Iterables 5 Esta clase tiene varios atributos (todos ellos consultables y modificables), a saber: Value: almacena la cadena del captcha. Filename: almacena el nombre del archivo en el que se guarda el captcha. Width: almacena el ancho en píxeles que tiene el captcha. Height: almacena el alto en píxeles que tiene el captcha. Para crear objetos de tipo Captcha, se dispone de tres constructores; al primero se le pasa como parámetro el valor de la cadena, al segundo se le pasa también el nombre del fichero y, por último, al tercero también se le pasan las dimensiones. Por ejemplo, para crear el captcha anterior bastaría con hacer Captcha c = new CaptchaImpl( bxdcha ). Para almacenar el captcha en un archivo JPG basta con invocar el método c.createjpg(). Este método genera una imagen JPG con las dimensiones indicadas en los atributos height y width, con el valor del captcha, y con el nombre de archivo indicado en filename. Para crear la secuencia de Captchas vamos a seguir la misma técnica que en los ejercicios anteriores. El diagrama de clases es el siguiente: Fíjese que al constructor del iterable se le pasa el número de captchas que se quieren generar (numcaptchas) y el tamaño que tiene la cadena (numchar). Además, tenga en cuenta que el iterador debe crear la cadena con el valor del Captcha, no los archivos que almacenarán las imágenes. Para generar secuencias de caracteres de letras minúsculas utilice lo siguiente: Character caracter = (char) (Math.random() * 26 + 'a'); El método random() genera un número aleatorio entre 0 y 1. Si lo multiplicamos por 26 (número de letras del alfabeto entre a y z en código ASCII), obtenemos un número aleatorio entre 0 y 26. Si a ese valor se le suma el código asociado al carácter a y truncamos, resultará en un número que identifica el carácter aleatorio extraído del alfabeto original.
Boletín de problemas 15: Factorías e Iterables 6 Ejecute un test que cree una secuencia de 10 captchas con un tamaño de 6 caracteres y los almacene en disco. Estos son algunos ejemplos: EJERCICIO 6: FACTORÍA DE ITERABLES VIRTUALES Defina una clase denominada IterablesVirtuales que sea la responsable de crear los iterables virtuales definidos en los ejercicios 2, 3 y 4. Cree una clase de test TestFactoriaIterables y compruebe que los distintos iterables funcionan correctamente. EJERCICIO 7: FACTORÍA DE VUELOS En este ejercicio vamos a practicar con el cálculo de las propiedades compartidas en las factorías. Para ello, defina una factoría para Vuelo que calcule las siguientes propiedades: Número de instancias creadas. Recaudación máxima de los vuelos creados. Recaudación mínima de los vuelos creados. Ciudades destino. Número de plazas totales ofertadas por la aerolínea. Realice una clase de Test para probar la factoría y comprobar que todo funciona correctamente (tenga en cuenta que estas propiedades sólo muestran información de los objetos en el momento de su creación).