Una arquitectura basada en capas
Cuando desarrollamos una aplicación podemos asemejar la
tarea a la construcción de un edificio.
Un proyecto de software orientado a objetos SIEMPRE debe
basarse en capas.
Cada capa tiene una responsabilidad definida:
è
El usuario solicita un servicio mediante la capa
de presentación
è
El sistema resuelve la petición en la capa de
negocio
è
La capa del negocio se apoya en la capa de
persistencia que se encarga de guardar y recupear objetos de la base de datos.
En cada capa deben crearse las clases y objetos necesarios:
è
Presentación:
VentanaPrincipa, MenuEdicion, BotonAceptar, BotonImprimir… Jurame, JButton,
JMenu, ActionEvent, KeyEvent…
è
Negocio: Connection,
ResultSet, Statement…
Pueden crearse tantas capas como sean requeridas
(normalmente tres o más).
La ingeniería del software orientada a objetos
Se encarga de desarrollar productos de software de calidad
en un tiempo y coste pactados de antemano.
Según el enfoque que adoptemos al modelar el problema
hablamos de Ingeniería de software:
è
Estructurada.
El ladrillo es el concepto de función y la librería o módulo que las
agrupa.
Técnicas. Diagramas de flujo de datos, entidad – relación,
diagramas de Constantine, pseudocódigos…
è
Orientada
a objetos. El ladrillo que usamos es la clase / objeto y el paquete como
elemento contenedor.
Técnicas. Diagramas de casos de uso, de clases, de secuencia, de
colaboración, mapeo de objetos a bases de datos relacionales…
La mayoría de las técnicas usadas para modelar un problema
con orientación a objetos suelen plasmarse en diagramas UML (Unified Modelling
Language).
Los diagramas UML los podemos clasificar según el modelado
que hacen del sistema:
è
Modelo de
requisitos. Diagramas de casos de uso
è
Modelo
estático. Diagrama de clases
è
Modelo
dinámico. Diagramas de secuencia
Durante el curso hemos creado diagramas de clases con
notación UML, que representan la vista estática del sistema.
Una metodología de desarrollo concreta las fases, tareas,
técnicas y productos que se deben realizar para obtener un producto de calidad.
Un paseo por la API
Fecha y hora
Las clases que necesitamos son:
è
Date. Representa
un instante de tiempo específico con precisión de milisegundos
è
Calendar.
Es una colección de propiedades y métodos que facilitan el trabajo con
instantes de tiempo
è
GregorianCalendar.
Implementa los métodos abstractos heredados de Calendar tomando como referencia
el calendario gregoriano (usado en casi todo el mundo).
Date. Actualmente deprecated
Calendar. Al ser demasiado
abstracta no podemos crear un objeto de la clase Calendar, sino que tendremos
que hacerlo a través de GregorianCalendar.
GregorianCalendar
ahoraCal = new GregorianCalendar();
O bien
Calendar
ahoraCal = new GregorianCalendar();
Propiedades públicas y estáticas de Calendar:
·
YEAR. Año
·
MONTH. Mes,
entre 0 y 11
·
DAY_OF_MONTH.
Día del mes
·
DAY_OF_WEEK.
Día de la semana entre 1 (Sunday) y 7 (Saturday)
·
HOUR.
Hora antes o después del medio día (en intervalos de doce horas).
·
HOUR_OF_DAY.
La hora absoluta del día (en intervalos de 24 horas)
·
MINUTE.
El minuto dentro de la hora
·
SECOND.
El segundo dentro del minuto
·
Y muchos
más…
Métodos útiles
+
int get(int campo)
Ejemplo
int
dia, mes, anio;
GregorianCalendar
ahoraCal = GregorianCalendar();
anio
= ahoraCal.get(Calendar.YEAR);
mes
= ahoraCal.get(Calendar.MONTH);
dia
= ahoraCal.get(Calendar.DAY_OF_MONTH);
System.out.println(“Hoy
es ” + dia + “/” + mes + “/” + anio);
Para establecer valores de una fecha
+
void set(int anio, int mes, int dia)
+
void set(int anio, int mes, int dia, int hora, int min, int seg);
+
void set(int campo, int nuevoValor);
Para sumar o restar tiempo a una fecha
+
void add(int campo, int cantidad);
Ejemplo
GregorianCalendar
calen = -GregorianCalendar();
calen.add(Calendar.YEAR,
-1);
System.out.prinln(“Año
pasado = ” + calen.get(Calendar.YEAR);
Para comparar instantes temporales (igual que Date)
+
boolean before(Calendar instante);
+
boolean after(Calendar instante);
+
boolean equals(Calendar instante);
GregorianCalendar
ahora = new GregorianCalendar();
System.out.pritln(“El
coche ha parado el motor a las ” + ahora.get(Calendar.HOUR_OF_DAY) + “ “ +
ahora.get(Calendar.MINUTE) + “:” + ahora.get(Calendar.SECOND));
Las clases envoltorio de los tipos primitivos
Los tipos primitivos (int, doublé, boolean) no son objetos, sin embargo
en ciertas ocasiones nos podría interesar que lo fuesen.
En el paquete java.lang se incluye un conjunto de clases que envuelven
a cada tipo primitivo, dotándolo de métodos y propiedades útiles.
Number y su descendencia
Number es una clase abstracta que define seis métodos que convierten
los números de un formato a otro:
int
intValue(); // Devuelve el valor envuelto convertido a int
double
doubleValue(); // Devuelve el valor envuelto convertido a doublé
…
Tomemos integer como ejemplo de subclase de Number y veamos que nos
ofrece.
Propiedades públicas y estáticas para consultar el mínimo y máximo
número representable por un int.
è
MAX_VALUE
è
MIN_VALUE
Constructores:
integer(int
valor);
integer(String
cadena) throws NumberFormatException;
Métodos estáticos para la conversión de String a int
static
int parseInt(String cadena) throws NumerFormatException;
static
int parseInt(String cadena, int base) throws NumberFormatException;
Ejemplos
integer.parseInt(“123”);
à
devuelve 123
integer.parseInt(“11111111”);
à
Devuelve 255
integer.parseInt(“FF”,16);
à
Devuelve 255
integer.parseInt(“FF”,10);
à
NumberFormatException
Además de los métodos heredados de Nuber hay más métodos que se pueden
consultar en la API.
Ahora vamos a fijarnos en la clase Caracter que envuelve a un char
(carácter en Unicode).
Aquí se presenta un conjunto de métodos estáticos muy útiles
static
int getNumericValue(char c);
static
boolean isDigit(char c);
static
boolean isletter(char c);
static
boolean isLetterOrDigit(char c);
static
boolean isLowerCase(char c);
static
boolean isUpperCase(char c);
static
char toLowerCase(char c);
Ejemplo
char
c = ‘9’;
int
entero;
if
(caracter.isDigit(c))
entero = carácter.getNumericValue(c);
else
c = carácter.toUpperCase(c);
La entrada y salida en Java. Los streams
La entrada y salida de un programa se refiere a las comunicaciones que
tiene dicho programa con “su entorno” (usuario, ficheros, red, pantalla, otros
programas…)
Al igual que en C y C++, Java usa el concepto de stream para gestionar
las comunicaciones.
Un stream representa a una corriente o flujo de datos que sale o entra
en nuestro programa.
Clasificicación de los Streams
Según la dirección a la que viajan los datos:
è
De entrada
è
De salida
Según el tipo de dato que manejan:
è
De bytes (8 bits)
è
De caracteres (en Unicode: 16 bits o más).
è
De líneas de caracteres
è
De datos
è
De objetos
Según su comportamiento
è
Transportadores.
Se limitan al transporte de los datos
è
Transformadores.
Cambian los datos y los transportan
è
Retenedores.
Almacenan datos y los transportan
En el paquete java.io se concentran la mayoría de las clases que
representan streams en Java.
Streams de ENTRADA basados en
bytes
InputStream{abstracta}
ByteArrayInputStream // 1
ObjectInputStream // 1
FileInputStream // 1
FilterInputStream // 2
DataInoutStream // 3
BufferedInputStream // 4
Significados:
1.
Proporciona al programa un flujo de bytes procedentes
de un array, un objeto o un fichero
2.
Esta clase y su descendencia son streams
transformadores
3.
Permite leer de una vez datos primitivos (int, double,
boolean…), no bytes a byte
4.
Permite almacenar en un buffer los byte leídos de otro
stream de entrada de bytes
Streams de ENTRADA basados en
caracteres UNICODE
Reader{abstracta}
StringReader // 1
BufferedReader //2
InputStreamReader // 3
FileReader // 4
Significados:
1.
Proporciona al programa un flujo de caracteres UNICODE procedentes
de un objeto String
2.
Permite almacenar en un buffer los caracteres UNICODE
leídos de otro stream de entrada de caracteres
3.
Permite transformar a caracteres UNICODE los bytes de
un stream basados en bytes, teniendo en cuenta la codificación local de
caracteres
4.
Permite la lectura directa de caracteres de un fichero
de texto
Streams de SALIDA basasdos en
bytes
OutputStream{abstracta}
ByteArrayOutputStream
ObjectOutputStream
FileOutputStream
FilterOutputStream
DataOutputStream
BufferedOutputStream
Streams de SALIDA de caracteres
UNICODE
Writer{abstracta}
PrintWriter
BufferedWiter
OutputStreamWriter
FileWriter
Los streams se pueden concetar unos con otros, combinando sus
funcionalidades.
Ejemplo:
Partimos de un flujo de bytes de entrada.
Ahora lo combinamos con otro que convierte los bytes a caracteres
UNICODE.
Y por último, lo combinamos con otro que es capaz de almacenar en un
buffer dichos caracteres.
Esto es precisamente lo que hay que hacer para poder leer datos que el
usuario introduce por teclado.
La clase System que representa al sistema nos devuelve un stream de
bytes a través de su propiedad estática in.
A continuación convertimos el stream de bytes obtenido a un stream de
caracteres UNICODE mediante la clase InputStreamReader.
InputStreamReader
isr = new InputStreamReader(System.in);
Con lo que obtendríamos
Por último lo combinamos con BufferedReader que es capaz de almacenar
los caracteres leídos en un buffer, mejorando la eficacia en el acceso al
teclado.
BufferedReader
teclado = new BufferedReader(isr);
Ahora podríamos usar el stream teclado para leer caracteres UNICODE de
forma eficiente.
Ejemplo:
String
cadena = teclado.readLine();
//
Lee hasta encontrar un INTRO
//
Lee cualquier caracter del alfabeto español
Clase teclado
import
java.io.*
public
class Teclado{
private InputStreamReader filtro;
private BufferedReader teclado;
public Teclado(){
filtro = new InputStreamReader(System.in);
teclado = new BufferedReader(filtro);
}
public String.leerString(String cadena)
throws IOException{
System.out.println(cadena); // Pedir que
debe escribir el usuario
return (teclado.readLine());
}
public byte leerByte() throws IOException{
return(Byte.parseByte(teclado.readLine());
}
public char leerChar(){
return ((char) teclado.read());
}
}
Teclado
teclado = new Teclado();
try{
String cadena = teclado.leerString(“Ruta del fichero”);
File fichero = new File(cadena);
if (fichero.exists()){
System.out.println(rutaCompila +
fichero.getAbsolutePath() + “es fichero ” + fichero.isFile() + “es directorio”
+ fichero.isDirectory() + “se puede leer ” + fichero.canRead() + “se puede
escribir ” +fichero.canwrite());
}
else
System.out.println(“fallo en entrada /
salida”);
}
catch(IOException
e){
System.out.println(“Fallo en entrada /
salida”);
}
0 comments:
Publicar un comentario