Você está na página 1de 74

Contenido

UNIDAD I PROGRAMACION CON PATRONES DE DISEÑO .......................................... 3


1.1 CONCEPTOS BASICOS DE PATRONES ...................................................................... 3
1.1.1 Definición de patrón ..................................................................................................... 3
1.1.2 Clasificación de patrones ............................................................................................ 6
1.2 PATRÓNES DE DISEÑO ................................................................................................... 8
1.2.1 Definición de patrones de diseño............................................................................... 8
Patrones Creacionales .................................................................................................... 8
Patrones Estructurales ................................................................................................. 10
Patrones De Comportamiento..................................................................................... 10
1.2.2 Sintaxis para la implementación de patrones de diseño ...................................... 11
1.2.3 Aplicaciones ................................................................................................................ 13
Ejemplo De La Aplicación De Patrones En Yii2 .............................................................. 14
UNIDAD II CONCURRENCIA DE HILOS ............................................................................ 15
2.1 CONCEPTOS BÁSICOS. ............................................................................................. 15
2.1.1 Definición de concurrencia. ....................................................................................... 15
2.1.2 Definición de Hilo........................................................................................................ 16
2.2. IMPLEMENTACIÓN DE HILOS ................................................................................. 17
2.2.1. Estados de un Hilo .................................................................................................... 17
2.2.2. Prioridades de Hilos .................................................................................................. 20
2.2.3. Sincronización de Hilos ............................................................................................ 27
2.2.4. Aplicaciones ............................................................................................................... 30
Ejemplo de hilos ................................................................................................................... 30
UNIDAD III APLICACIONES DE CLASES E INTERFACES INTERNAS ...................... 36
3.1. CLASES INTERNAS .................................................................................................... 36
3.1.1 Definición de Clase .................................................................................................... 36
3.1.2 Definición de Clase Interna ....................................................................................... 37
3.1.3 Aplicación de Clases Internas .................................................................................. 39
3.2. INTERFACES ................................................................................................................ 41
3.2.1 Definición de Interfaz ................................................................................................. 41
3.2.2 Sintaxis para la Implementacion de Interfaz .......................................................... 42
3.2.3 Aplicaciones de Interfaz ............................................................................................ 44
Código para definir una interfaz ......................................................................................... 45
Implementación de interfaces............................................................................................. 45
UNIDAD IV FUNDAMENTOS DE INTERFACES GRAFICAS DE USUARIO ............... 47
4.1. CONCEPTOS BASICOS ............................................................................................. 47
4.1.1 Definicion de GUI ....................................................................................................... 47
4.1.2 Elementos Básicos de una GUI ............................................................................... 47
4.2 IMPLEMENTACION ...................................................................................................... 49
4.2.1 Implementacion De Una GUI En Java .................................................................... 49
4.2.2 Implementacion De Una GUI En C#........................................................................ 55
UNIDAD V MAPEO OBJETO RELACIONAL ..................................................................... 58
5.1. CONCEPTOS BASICOS ............................................................................................. 58
5.1.1 Justificación del Mapeo Objeto-Relacional............................................................. 58
5.1.2 Alternativa al Mapeo Objeto-Relacional.................................................................. 60
5.2 Implementación .............................................................................................................. 62
5.2.1 Uso de motores de Persistencia .............................................................................. 63
ANEXOS .................................................................................................................................... 65
USO DE INTERFAZ GRAFICA EN YII2............................................................................... 66
Modelo vista controlador ..................................................................................................... 66
Creación de los modelos a utilizar .................................................................................... 66
1.3 Vista de los modelos creados ...................................................................................... 67
APLICACIÓN DE INTERFAZ ................................................................................................ 67
1.4 Roles de usuario .............................................................................................................. 67
1.5 Asignacion de Permisos para cada Usuario ............................................................ 68
1.6 Creacion de los Roles y Permisos en el modelo vista controlador. .................. 68
1.7 Creación del rolles .......................................................................................................... 69
1.8 Rolles .................................................................................................................................. 69
1.9 Creacion de Permisos .................................................................................................... 70
1.10 Creacion de un nuevo permiso.................................................................................. 70
1.11 Asignacion de los permisos al Roll. ......................................................................... 71
1.12 Acceso a la interfaz de usuario con los permisos asginados ........................... 71
IMPLEMENTACION DE LAS INTERFACES ...................................................................... 72
1.13 Inplementacion de la base de datos ......................................................................... 72
1.15 Elaboracion de la base de datos ............................................................................... 73
1.17 Elaboracion de reportes mediante la interfaz grafica de usuario .................... 74
UNIDAD I PROGRAMACION CON PATRONES DE DISEÑO

1.1 CONCEPTOS BASICOS DE PATRONES

1.1.1 Definición de patrón

Un patrón es un tipo de tema de sucesos u objetos recurrentes, como por


ejemplo grecas, a veces referidos como ornamentos de un conjunto de objetos.
Más abstractamente, podría definirse "patrón" como aquella serie de variables
constantes, identificables dentro de un conjunto mayor de datos.
Estos elementos se repiten de una manera predecible. Puede ser una plantilla o
modelo que puede usarse para generar objetos o partes de ellos, especialmente
si los objetos que se crean tienen lo suficiente en común para que se infiera la
estructura del patrón fundamental, en cuyo caso, se dice que los objetos exhiben
un único patrón.
Los patrones más básicos, llamados teselaciones, se basan en la repetición y
la periodicidad. Una única plantilla, azulejo o célula, se combina mediante
duplicados sin cambios o modificaciones. Por ejemplo, osciladores armónicos
simples producen repetidos patrones de movimiento.
Otros patrones, como la teselación de Penrose y los
patrones indios Pongal o Kolam, usan simetría, que es una forma de repetición
finita, en lugar de una traslación, que puede repetirse hasta el infinito. Los
patrones fractales también utilizan aumentos o escalas que producen un efecto
conocido como autosimilaridad o invariancia de escala. Algunas plantas, como
los helechos, incluso generan un patrón usando una transformación afín que
combina la traslación, con el escalado, la rotación y la reflexión.
La concordancia de patrones es el acto de comprobar la presencia de los
componentes de un patrón, mientras que la detección de patrones subyacentes
se conoce como el reconocimiento de patrones. La cuestión de cómo surge un
patrón es llevado a cabo a través del trabajo científico de la formación de
patrones.
El reconocimiento de patrones es tanto más complejo cuando las plantillas se
utilizan para generar variantes. La informática, la etología y la psicología son
ámbitos donde se estudian los patrones.
"Un patrón tiene una integridad independiente del medio en virtud del cual se ha
recibido la información de que existe. Cada uno de los elementos químicos es
una integridad de patrón. Cada individuo también. La integridad de patrón de la
persona humana está en constante evolución y no es estática."
Patrones observables
Cualquiera de los cinco sentidos puede detectar patrones directamente.
 Visuales
Los patrones visuales son muy comunes, pudiendo ser desde simples motivos
decorativos (rayas, zig-zags, o lunares) a otros más complicados, aunque se
pueden encontrar en cualquier parte, en la naturaleza y el arte. Por ejemplo, las
teselaciones de Penrose.
 Arte
Un patrón recurrente en una obra de arte puede constituir un motivo.
El número áureo (aproximadamente 1.618) se encuentra con frecuencia en la
naturaleza. Está definido por dos números, que forman una proporción tal que (a
+ b)/a = a/b (a/b es la proporción áurea). Este patrón fue explotado por Leonardo
da Vinci en sus obras. La proporción áurea, en la naturaleza, se encuentra desde
las espirales de flores a la simetría del cuerpo humano (como lo expresó en
Leonardo en su Hombre de Vitruvio, una de las obras más referenciadas y
reproducidas del arte de siempre, y que todavía es utilizado por muchos artistas).
"El arte es la imposición de un patrón a la experiencia, y nuestro goce estético
es el reconocimiento de un patrón."
[ (1861-1947), filósofo y matemático inglés. Diálogos, 10 de junio de 1943.
Los patrones de abstracción no puede ser observables directamente, como es el
caso de los patrones en las matemáticas.
Matemáticas
Las matemáticas son comúnmente descritas como la "Ciencia del patrón."
Cualquier secuencia de números que pueda ser modelada por una función
matemática es considerada un patrón.
En la teoría de patrones, los matemáticos han intentado describir el mundo en
términos de patrones. El objetivo es exponer el mundo de una manera sencilla,
computacionalmente.
Los patrones son comunes en muchas áreas matemáticas. Los decimales
periódicos son un ejemplo. Son secuencias de repetición de dígitos que se
repiten infinitamente. Por ejemplo, 1 dividido por 81 dará lugar a 0,012345679...
los números 0-9 (excepto el 8) se repetirán continuamente; 1/81 es un decimal
periódico.
Los fractales son patrones matemáticos que son invariantes de escala. Esto
significa que la forma del modelo no depende de lo cerca que se mire. Se
encuentra auto similitud en los fractales. Ejemplos de fractales naturales se
encuentran en las líneas costeras y las formas de los árboles, que repiten su
forma, independientemente de la ampliación con que se vea. Si bien la
apariencia externa de los patrones de auto similitud puede ser bastante
compleja, las reglas necesarias para describir o producir su formación pueden
ser muy simples (por ejemplo, los sistemas de Lindenmayer para la descripción
de las formas de los árboles).
 Informática
En informática, pueden diseñarse complejos modelos matemáticos para crear
patrones más complejos. Los patrones se pueden encontrar en todas las ramas
de la informática.
Un importante uso de patrones se da en la idea de patrones de diseño. Los
patrones de diseño son soluciones generales para resolver problemas de
programación. No van a resolver un problema específico, pero proporcionan una
especie de esquema arquitectónico que puede ser reutilizado con el fin de
acelerar el proceso de desarrollo de un programa.[cita requerida] Los patrones
de diseño han proporcionado la primera piedra para que la informática entre
realmente en el campo de la ingeniería.
Ciencia
En geología, la estructura cristalina de un mineral está compuesta por un patrón
recurrente. De hecho, este es uno de los cinco requisitos de un mineral. Los
minerales deben tener una composición química fija en una estructura repetitiva,
como una matriz de cristal. Para obtener una estructura cristalina de 2
dimensiones, hay 10 diferentes enrejados planos posibles. En 3 dimensiones,
son posibles 32 patrones. Estos son llamados redes de Bravais. También se da
en los autómatas celulares o en los cristales.
1.1.2 Clasificación de patrones

Este es el listado de los patrones de diseño más conocidos. Poco a poco iré
escribiendo artículos sobre cada uno de ellos y los iré enlazando aquí. Es un
proceso largo porque son muchos y quiero encontrar la mejor forma de
explicarlos, pero llegará el día en que tengamos aquí un listado completo que te
sirva de referencia.
Los patrones se dividen en distintos grupos según el tipo de problema que
resuelven, a saber:
 Patrones creacionales
Son los que facilitan la tarea de creación de nuevos objetos, de tal forma que el
proceso de creación pueda ser desacoplado de la implementación del resto del
sistema.
Los patrones creacionales están basados en dos conceptos:
Encapsular el conocimiento acerca de los tipos concretos que nuestro sistema
utiliza. Estos patrones normalmente trabajarán con interfaces, por lo que la
implementación concreta que utilicemos queda aislada.
Ocultar cómo estas implementaciones concretas necesitan ser creadas y cómo
se combinan entre sí.
Los patrones creacionales facilitan la tarea de creación de nuevos objetos
encapsulando el proceso.
Los patrones creacionales más conocidos son:
Abstract Factory, Factory Method, Builder, Singleton, Prototype
 Patrones estructurales
Son patrones que nos facilitan la modelización de nuestros
software especificando la forma en la que unas clases se relacionan con otras.
Los patrones estructurales especifican la forma en que unas clases se relacionan
con otras.
Estos son los patrones estructurales que definió la Gang of Four:
Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy

 Patrones de comportamiento
En este último grupo se encuentran la mayoría de los patrones, y se usan
para gestionar algoritmos, relaciones y responsabilidades entre objetos.
Los patrones de comportamiento gestionan algoritmos, relaciones y
responsabilidades entre objetos.
Los patrones de comportamiento son:
Command, Chain of responsibility, Interpreter, Iterator, Mediator, Memento,
Observer, State, Strategy, Template Method, Visitor
1.2 PATRÓNES DE DISEÑO

1.2.1 Definición de patrones de diseño

Los patrones de diseño son el esqueleto de las soluciones a problemas comunes


en el desarrollo de software. En otras palabras, brindan una solución ya probada
y documentada a problemas de desarrollo de software que están sujetos a
contextos similares. Debemos tener presente los siguientes elementos de un
patrón: su nombre, el problema (cuando aplicar un patrón), la solución
(descripción abstracta del problema) y las consecuencias (costos y beneficios).
Grande fue mi sorpresa al averiguar que existen varios patrones de diseño
popularmente conocidos, los cuales se clasifican como se muestra a
continuación:

 Patrones Creacionales: Inicialización y configuración de objetos.


 Patrones Estructurales: Separan la interfaz de la implementación. Se
ocupan de cómo las clases y objetos se agrupan, para formar estructuras
más grandes.
 Patrones de Comportamiento: Más que describir objetos o clases,
describen la comunicación entre ellos.
Veamos un poco en qué consisten los distintos tipos de patrones, cuáles son sus
fines y qué beneficios nos aportan.

Patrones Creacionales

Fábrica Abstracta ( Abstract Factory )

El problema a solucionar por este patrón es el de crear diferentes familias de


objetos, como por ejemplo la creación de interfaces gráficas de distintos tipos
(ventana, menú, botón, etc.).

Método de Fabricación ( Factory Method )


Parte del principio de que las subclases determinan la clase a implementar.

public class ConcreteCreator extends Creator


{
protected Product FactoryMethod()
{
return new ConcreteProduct();
}
}
public interface Product{}
public class ConcreteProduct implements Product{}
public class Client
{
public static void main(String args[])
{
Creator UnCreator;
UnCreator = new ConcreteCreator();
UnCreator.AnOperations();
}
}

Prototipado ( Prototype )

Se basa en la clonación de ejemplares copiándolos de un prototipo.

Singleton

Restringe la instanciación de una clase o valor de un tipo a un solo objeto.

public sealed class Singleton


{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton()
{
System.Windows.Forms.MessageBox.Show("Nuevo Singleton");
}
public static Singleton GetInstance
{
get
{
if (instance == null)
{
lock(syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}

MVC ( Model View Controler )

Este patrón plantea la separación del problema en tres capas: la capa model,
que representa la realidad; la capa controler , que conoce los métodos y
atributos del modelo, recibe y realiza lo que el usuario quiere hacer; y la
capa vista, que muestra un aspecto del modelo y es utilizada por la capa anterior
para interaccionar con el usuario.
Patrones Estructurales

 Adaptador (Adapter): Convierte una interfaz en otra.


 Puente (Bridge): Desacopla una abstracción de su implementación
permitiendo modificarlas independientemente.
 Objeto Compuesto (Composite): Utilizado para construir objetos
complejos a partir de otros más simples, utilizando para ello la
composición recursiva y una estructura de árbol.
 Envoltorio (Decorator): Permite añadir dinámicamente funcionalidad a una
clase existente, evitando heredar sucesivas clases para incorporar la
nueva funcionalidad.
 Fachada (Facade): Permite simplificar la interfaz para un subsistema.
 Peso Ligero (Flyweight): Elimina la redundancia o la reduce cuando
tenemos gran cantidad de objetos con información idéntica.
 Apoderado (Proxy): Un objeto se aproxima a otro.

Patrones De Comportamiento

 Cadena de responsabilidad (Chain of responsibility): La base es permitir


que más de un objeto tenga la posibilidad de atender una petición.
 Orden (Command): Encapsula una petición como un objeto dando la
posibilidad de “deshacer” la petición.
 Intérprete (Interpreter): Intérprete de lenguaje para una gramática simple
y sencilla.
 Iterador (Iterator): Define una interfaz que declara los métodos necesarios
para acceder secuencialmente a una colección de objetos sin exponer su
estructura interna.
 Mediador (Mediator): Coordina las relaciones entre sus asociados.
Permite la interacción de varios objetos, sin generar acoples fuertes en
esas relaciones.
 Recuerdo (Memento): Almacena el estado de un objeto y lo restaura
posteriormente.
 Observador (Observer): Notificaciones de cambios de estado de un
objeto.
1.2.2 Sintaxis para la implementación de patrones de diseño

El patrón de diseño Visitor se utiliza para separar la lógica u operaciones que se


pueden realizar sobre una estructura compleja. En ocasiones nos podemos
encontrar con estructuras de datos que requieren realizar operaciones sobre ella,
pero estas operaciones pueden ser muy variadas e incluso se pueden desarrollar
nuevas a medida que la aplicación crece.
A medida que estas operaciones crecen, el número de operaciones que deberá
tener la estructura también crecerá haciendo que administrar la estructura sea
muy complejo. Por esta razón el patrón de diseño Visitor propone la separación
de estas operaciones en clases independientes llamadas Visitantes, las cuales
son creadas implementando una interface común y no requiere modificar la
estructura inicial para agregar la operación.

Estructura del patrón Visitor.


A continuación se explican los componentes que conforman el patrón.
Cliente: Componente que interactúa con la estructura (element) y con el
Visitante, éste es responsable de crear los visitantes y enviarlos al elemento para
su procesamiento.
Element: Representa la raíz de la estructura, en forma de árbol, sobre la que
utilizaremos el Visitante. Este objeto por lo general es una interface que define
el método accept y deberán implementar todos los objetos de la estructura.
ConcreteElement: Representa un hijo de la estructura compuesta, la estructura
completa puede estar compuesta de un gran número de estos objetos y cada
uno deberá implementar el método accept.
IVisitor: Interface que define la estructura del visitante, la interface deberá tener
un método por cada objeto que se requiera analizar de la estructura (element).
ConcreteVisitor: Representa una implementación del visitante, esta
implementación puede realizar una operación sobre el element. Es posible tener
todos los ConcreteVisitor necesarios para realizar las operaciones que
necesitemos.

Diagrama de secuencia del patrón Visitor.

El cliente crea la estructura (Element).


El cliente crea la instancia del Visitante a utilizar sobre la estructura.
El cliente ejecuta el método accept de la estructura y la envía al Visitante.
El Element le dice al Visitante con que método lo debe procesar.
El Visitante deberá tener un método para cada tipo de clase de la estructura.
El Visitante analiza al Element mediante su método visitElement y repite el
proceso de ejecutar el método accept sobre los hijos del Element. Nuevamente
el Visitante deberá tener un método para procesar cada clase hija de la
estructura.
El ConcreteElementA le indica al Visitante con qué método debe procesarlo, el
cual es visitElementA.
La visitante continúa con los demás hijos de Element y esta vez ejecuta el
método accept sobre el ConcreteElementB.
El ConcrteElementB le indica al Visitante con qué método debe procesarlo, el
cual es visitElementB.
Finalmente el Visitante termina la operación sobre la estructura cuando ha
recorrido todos los objetos, obteniendo un resultado que es solicitado por
el cliente mediante el método getResults (el resultado es opcional ya que existen
operaciones que no arrojan resultados).

1.2.3 Aplicaciones

Además de su aplicación directa en la construcción de software en general, y


derivado precisamente del gran éxito que han tenido, los patrones de diseño han
sido aplicados a múltiples ámbitos concretos produciéndose "lenguajes de
patrones" y extensos "catálogos" de la mano de diversos autores.
En particular son notorios los esfuerzos en los siguientes ámbitos:

 Patrones de interfaces de usuario, esto es, aquellos que intentan definir las
mejores formas de construir interfaces hombre-máquina (véase Interacción
persona-computador, Interfaz gráfica de usuario).
 Patrones para la construcción de sistemas empresariales, en donde se
requieren especiales esfuerzos en infraestructuras de software y un nivel de
abstracción importante para maximizar factores como la escalabilidad o el
mantenimiento del sistema.
 Patrones para la integración de sistemas (véase Integración de aplicaciones
empresariales), es decir, para la intercomunicación y coordinación de
sistemas heterogéneos.
 Patrones de flujos de trabajo, esto es para la definición, construcción e
integración de sistemas abstractos de gestión de flujos de trabajo y procesos
con sistemas empresariales. Véase también BPM.
Ejemplo De La Aplicación De Patrones En Yii2
UNIDAD II CONCURRENCIA DE HILOS

2.1 CONCEPTOS BÁSICOS.

La idea de programación concurrente siempre ha estado asociada a los sistemas


operativos: Un sólo procesador de gran capacidad debía repartir su tiempo entre
muchos usuarios. La programación de estos sistemas se hacía a bajo nivel
(ensamblador). Posteriormente aparecerían lenguajes de alto nivel con soporte
para este tipo de programación. Su utilización y potencial utilidad se apoya en:
threads o hilos, java e internet.

2.1.1 Definición de concurrencia.

Se habla de concurrencia cuando ocurren varios sucesos de manera


contemporánea. En base a esto, la concurrencia en computación está asociada
a la “ejecución” de varios procesos que coexisten temporalmente.
Para definirla correctamente, debemos diferencias entre programa y proceso.

Programa: Conjunto de sentencias/instrucciones que se ejecutan


secuencialmente. Se asemeja al concepto de clase dentro de la POO. Es por
tanto un concepto estático.

Proceso: Básicamente, se puede definir como un programa en ejecución. Líneas


de código en ejecución de manera dinámica. Se asemeja al concepto de objeto
en POO.
¿Cuales son sus beneficios?

● Velocidad de ejecución. Al subdividir un programa en procesos, éstos se


pueden “repartir” entre procesadores o gestionar en un único procesador según
importancia.

● Solución a problemas de esta naturaleza. Existen algunos problemas cuya


solución es más fácil utilizando esta metodología.

- Sistemas de control: Captura de datos, análisis y actuación (p.ej. sistemas de


tiempo real).

- Tecnologías web: Servidores web que son capaces de atender varias


peticiones concurrentemente, servidores de chat, email, etc.
- Aplicaciones basabas en GUI: El usuario hace varias peticiones a la aplicación
gráfica (p.ej. Navegador web).

- Simulación: Programas que modelan sistemas físicos con autono- -mía. -


Sistemas Gestores de Bases de Datos: Cada usuario un proceso.
2.1.2 Definición de Hilo.

Hilo (theread) llamado también proceso ligero o subproceso, es la unidad


de ejecución de un proceso y esta asociado con una secuencia de instrucciones
un conjunto de registros y una pila. Cuando se crea un proceso el S.O crea su
primer hilo (hilo primario) en la cual puede,a su vez,crear hilos adicionales. esto
pone de manifiesto que un proceso no ejecuta,si no que es sólo el espacio de
direcciones donde recide el código que es ejecutado mediante uno o más hilos.
En un S.O tradicional. Cada proceso tiene un espacio de direcciones y
un único hilo de control por ejemplo, considere que un programa que incluya la
siguiente secuencia de operaciones para actualizar el saldo de una cuenta
bancaria cuando se efectúa un nuevo ingreso:
Saldo=Cuenta.ObtenerSaldo ();
Saldo+=ingreso;
Cuenta.EstablecerSaldo (saldo);
Este modelo de programación, en el que se ejecuta un solo hilo, es en el que
estamos acostumbrados a trabajar habitualmente. Pero, siguiendo con el
ejemplo anterior piensa en un banco real; en el varios cajeros pueden
actuar simultáneamente. Ejecutar el mismo programa por cada uno de los
cajeros tiene un costo elevado (recuerde los recursos que necesita). En cambio
si el programa permitiera lanzar un hilo por cada petición de cada cajero para
actualizar una cuenta, estaríamos en el caso múltiples hilos
ejecutandose concurrente mente (multitriandi) . Esta característica ya es una
realidad en los S.O modernos de hoy y como consecuencia contemplada en los
lenguajes de programación actuales.
Cada hilo se ejecuta de forma estrictamente secuencial y tiene su propia pila en
estados de los registros de UCP y su propio contador de un programa en cambio
comparte el mismo espacio de direcciones, lo que significa compartir también las
mismas variables globales, el mismo conjunto de ficheros abiertos, procesos
hijos (no hilos hijos), señales, semáforos, etc.
Los hilos comparten la UCP de la misma forma que lo hacen los procesos
pueden crear hilos hijos y se pueden bloquear no obstante mientras un hilo del
mismo proceso, en el caso de hilos soportados por el kernel (núcleo del S.O:
programas en ejecución que hacen que el sistema funcione), no sucediendo lo
mismo con los hilos soportados por una aplicación por ejemplo en Windows
NT todos los hilos son soportados por el Kernel; imaginemos que alguien llaga a
un cajero para depositar dinero en una cuenta y casi al mismo tiempo un segundo
cliente realiza la misma operación sobre la misma cuanta en el segundo cajero
quedara bloqueado asta que el registro que esta siendo actualizado por el primer
cajero quede liberado.
2.2. IMPLEMENTACIÓN DE HILOS

La mayoria del soporte de java proporciona para trabajar con hilos recide en la
clase Theread del paquete java.lang, aunque también la clase Objecto, la
interfaz Runnable,la interfaz Thread.UncaughtExceptionHandler y las clases
ThreadGroup y ThreadLocal del mismo paquete,así como la máquina
virtual,proporcionan algún tipo de soporte.

2.2.1. Estados de un Hilo

Durante el ciclo de vida de un hilo, éste se puede encontrar en diferentes


estados. La figura siguiente muestra estos estados y los métodos que provocan
el paso de un estado a otro. Este diagrama no es una máquina de estados finita,
pero es lo que más se aproxima al funcionamiento real de un hilo.

Nuevo Thread
La siguiente sentencia crea un nuevo hilo de ejecución pero no lo arranca, lo deja
en el estado deNuevo Thread:
Thread MiThread = new MiClaseThread();
Thread MiThread = new Thread( new UnaClaseThread,"hiloA" );
Cuando un hilo está en este estado, es simplemente un objeto Thread vacío. El
sistema no ha destinado ningún recurso para él. Desde este estado solamente
puede arrancarse llamando al método start(), o detenerse definitivamente,
llamando al método stop(); la llamada a cualquier otro método carece de sentido
y lo único que provocará será la generación de una excepción de
tipoIllegalThreadStateException.
Ejecutable
Ahora obsérvense las dos líneas de código que se presentan a continuación:
Thread MiThread = new MiClaseThread();
MiThread.start();
La llamada al método start() creará los recursos del sistema necesarios para que
el hilo puede ejecutarse, lo incorpora a la lista de procesos disponibles para
ejecución del sistema y llama al método run() del hilo de ejecución. En este
momento se encuentra en el estado Ejecutable del diagrama. Y este estado
es Ejecutable y no En Ejecución, porque cuando el hilo está aquí no esta
corriendo. Muchos ordenadores tienen solamente un procesador lo que hace
imposible que todos los hilos estén corriendo al mismo tiempo. Java implementa
un tipo de scheduling o lista de procesos, que permite que el procesador sea
compartido entre todos los procesos o hilos que se encuentran en la lista. Sin
embargo, para el propósito que aquí se persigue, y en la mayoría de los casos,
se puede considerar que este estado es realmente un estado En Ejecución,
porque la impresión que produce ante el usuario es que todos los procesos se
ejecutan al mismo tiempo.
Cuando el hilo se encuentra en este estado, todas las instrucciones de código
que se encuentren dentro del bloque declarado para el método run(), se
ejecutarán secuencialmente.
Parado
El hilo de ejecución entra en estado Parado cuando alguien llama al
método suspend(), cuando se llama al método sleep(), cuando el hilo está
bloqueado en un proceso de entrada/salida o cuando el hilo utiliza su
método wait() para esperar a que se cumpla una determinada condición. Cuando
ocurra cualquiera de las cuatro cosas anteriores, el hilo estará Parado.
Por ejemplo, en el trozo de código siguiente:
Thread MiThread = new MiClaseThread();
MiThread.start();
try {
MiThread.sleep( 10000 );
} catch( InterruptedException e ) {
;
}
la línea de código que llama al método sleep():
MiThread.sleep( 10000 );
hace que el hilo se duerma durante 10 segundos. Durante ese tiempo, incluso
aunque el procesador estuviese totalmente libre, MiThread no correría. Después
de esos 10 segundos. MiThread volvería a estar en estado Ejecutable y ahora sí
que el procesador podría hacerle caso cuando se encuentre disponible.
Para cada una de los cuatro modos de entrada en estado Parado, hay una forma
específica de volver a estado Ejecutable. Cada forma de recuperar ese estado
es exclusiva; por ejemplo, si el hilo ha sido puesto a dormir, una vez transcurridos
los milisegundos que se especifiquen, él solo se despierta y vuelve a estar en
estado Ejecutable. Llamar al método resume() mientras esté el hilo durmiendo
no serviría para nada.
Los métodos de recuperación del estado Ejecutable, en función de la forma de
llegar al estadoParado del hilo, son los siguientes:
Si un hilo está dormido, pasado el lapso de tiempo
Si un hilo de ejecución está suspendido, después de una llamada a su
método resume()
Si un hilo está bloqueado en una entrada/salida, una vez que el comando de
entrada/salida concluya su ejecución
Si un hilo está esperando por una condición, cada vez que la variable que
controla esa condición varíe debe llamarse al método notify() o notifyAll()
Muerto
Un hilo de ejecución se puede morir de dos formas: por causas naturales o
porque lo maten (constop()). Un hilo muere normalmente cuando concluye de
forma habitual su método run(). Por ejemplo, en el siguiente trozo de código, el
bucle while es un bucle finito -realiza la iteración 20 veces y termina-:
public void run() {
int i=0;
while( i < 20 ) {
i++;
System.out.println( "i = "+i );
}
}
Un hilo que contenga a este método run(), morirá naturalmente después de que
se complete el bucle y run() concluya.
También se puede matar en cualquier momento un hilo, invocando a su
método stop(). En el trozo de código siguiente:
Thread MiThread = new MiClaseThread();
MiThread.start();
try {
MiThread.sleep( 10000 );
} catch( InterruptedException e ) {
;
}
MiThread.stop();
se crea y arranca el hilo MiThread, se duerme durante 10 segundos y en el
momento de despertarse, la llamada a su método stop(), lo mata.
El método stop() envía un objeto ThreadDeath al hilo de ejecución que quiere
detener. Así, cuando un hilo es parado de este modo, muere asíncronamente. El
hilo morirá en el momento en que reciba ese objeto ThreadDeath.
Los applets utilizarán el método stop() para matar a todos sus hilos cuando el
navegador con soporte Java en el que se están ejecutando le indica al applet
que se detengan, por ejemplo, cuando se minimiza la ventana del navegador o
cuando se cambia de página.
El método isAlive()
El interfaz de programación de la clase Thread incluye el método isAlive(), que
devuelve true si el hilo ha sido arrancado (con start()) y no ha sido detenido
(con stop()). Por ello, si el métodoisAlive() devuelve false, sabemos que estamos
ante un Nuevo Thread o ante un thread Muerto. Si devuelve true, se sabe que el
hilo se encuentra en estado Ejecutable o Parado. No se puede diferenciar
entre Nuevo Thread y Muerto, ni entre un hilo Ejecutable o Parado.

2.2.2. Prioridades de Hilos

En general, durante un período de tiempo determinado, los hilos de baja prioridad


reciben poco. Los hilos de alta prioridad reciben mucho. Como era de esperar,
la cantidad de tiempo de CPU que recibe un hilo tiene un profundo impacto en
sus características de ejecución y su interacción con otros hilos que se están
ejecutando actualmente en el sistema.
Es importante comprender que factores distintos de la prioridad de un hilo
también afectan la cantidad de tiempo de CPU que recibe un hilo. Por ejemplo,
si un hilo de alta prioridad está esperando algún recurso, quizás para la entrada
del teclado, se bloqueará y se ejecutará un hilo de menor prioridad. Sin embargo,
cuando ese hilo de alta prioridad obtiene acceso al recurso, puede adelantarse
al hilo de baja prioridad y reanudar la ejecución.
Otro factor que afecta la programación de los hilos es la forma en que el sistema
operativo implementa la multitarea. Por lo tanto, solo porque le dé a un hilo una
prioridad alta y a otro una prioridad baja no significa necesariamente que un hilo
se ejecutará más rápido o más a menudo que el otro. Es solo que el hilo de alta
prioridad tiene un mayor acceso potencial a la CPU.
Asignar prioridades a hilos
Cuando se inicia un hilo secundario, su configuración de prioridad es igual a la
de su hilo principal. Puede cambiar la prioridad de un hilo llamando a setPriority(),
que es un miembro de Thread. Esta es su forma general:
final void setPriority(int nivel)
El método java.lang.Thread.setPriority() cambia la prioridad del hilo al valor nivel.
Este método arroja IllegalArgumentException si el valor del parámetro nivel va
más allá del límite mínimo (1) y máximo (10).
Aquí, el nivel especifica la nueva configuración de prioridad para el hilo de
llamada. El valor del nivel debe estar dentro del
rango MIN_PRIORITY y MAX_PRIORITY. Actualmente, estos valores son 1 y
10, respectivamente. Para devolver un hilo a la prioridad predeterminada,
especifique NORM_PRIORITY, que actualmente es 5. Estas prioridades se
definen como variables finales estáticas dentro de Thread.
public static int MIN_PRIORITY: esta es la prioridad mínima que un hilo puede
tener. El valor es 1.
public static int NORM_PRIORITY: esta es la prioridad predeterminada de un hilo
si no lo define explícitamente. El valor es 5.
public static int MAX_PRIORITY: esta es la prioridad máxima de un hilo. El valor
es 10.
Puede obtener la configuración de prioridad actual llamando al
método getPriority() de Thread, que se muestra aquí:
final int getPriority()
El método java.lang.Thread.getPriority() devuelve la prioridad del hilo dado.

Ejemplo con getPriority en Java


class DemoPrioridadGet extends Thread
{
public void run()
{
System.out.println("Dentro del método run");
}

public static void main(String[]args)


{
DemoPrioridadGet t1 = new DemoPrioridadGet();
DemoPrioridadGet t2 = new DemoPrioridadGet();
DemoPrioridadGet t3 = new DemoPrioridadGet();

System.out.println("Prioridad del hilo t1 : " +


t1.getPriority()); // Por defecto 5
System.out.println("Prioridad del hilo t2 : " +
t2.getPriority()); // Por defecto 5
System.out.println("Prioridad del hilo t3 : " +
t3.getPriority()); // Por defecto 5

t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);

// t3.setPriority(21); arrojará IllegalArgumentException


System.out.println("Prioridad del hilo t1 : " +
t1.getPriority()); //2
System.out.println("Prioridad del hilo t2 : " +
t2.getPriority()); //5
System.out.println("Prioridad del hilo t3 : " +
t3.getPriority());//8

// Hilo Principal (Main thread)


System.out.print(Thread.currentThread().getName()+": ");
System.out.println("Prioridad del hilo Main : "
+ Thread.currentThread().getPriority());
// La prioridad del hilo principal se establece en 10
Thread.currentThread().setPriority(10);
System.out.println("Prioridad del hilo Main : "
+ Thread.currentThread().getPriority());
}
}
Salida:
Prioridad del hilo t1 : 5
Prioridad del hilo t2 : 5
Prioridad del hilo t3 : 5
Prioridad del hilo t1 : 2
Prioridad del hilo t2 : 5
Prioridad del hilo t3 : 8
main: Prioridad del hilo Main : 5
Prioridad del hilo Main : 10
El hilo con la prioridad más alta tendrá probabilidad de ejecución antes que otros
hilos. Supongamos que hay 3 hilos t1, t2 y t3 con prioridades 4, 6 y 1. Por lo
tanto, el hilo t2 se ejecutará primero según la prioridad máxima de 6,
después t1 se ejecutará y luego t3.
La prioridad predeterminada para el hilo principal es siempre 5, se puede cambiar
más tarde. La prioridad predeterminada para todos los demás hilos depende de
la prioridad del hilo principal.
Si dos hilos tienen la misma prioridad, entonces no podemos esperar qué hilo se
ejecutará primero. Depende del algoritmo del planificador de hilos (Round-Robin,
First Come First Serve, etc.)

Ejemplo con setPriority en Java


El siguiente ejemplo muestra los hilos en diferentes prioridades. Los hilos se
crean como instancias de Priority.
//Demostración de prioridades en hilos
class PrioridadHilos implements Runnable {
int contar;
Thread hilo;
static boolean stop=false;
static String actualNombre;

//Construye un nuevo hilo.


PrioridadHilos(String nombre){
hilo= new Thread(this,nombre);
contar=0;
actualNombre=nombre;
}

//Punto de entrada de hilo.


public void run(){
System.out.println(hilo.getName()+" iniciando.");
do {
contar++;
if (actualNombre.compareTo(hilo.getName())!=0){
actualNombre=hilo.getName();
System.out.println("En "+actualNombre);
}
}while (stop==false&&contar<10000000);
stop=true;
System.out.println("\n"+ hilo.getName()+" terminado.");
}
}
class DemoPrioridad{
public static void main(String[] args) {
PrioridadHilos ph1= new PrioridadHilos("Prioridad Alta");
PrioridadHilos ph2= new PrioridadHilos("Prioridad Baja");
PrioridadHilos ph3= new PrioridadHilos("Prioridad Normal #1");
PrioridadHilos ph4= new PrioridadHilos("Prioridad Normal #2");
PrioridadHilos ph5= new PrioridadHilos("Prioridad Normal #3");

//Establecer prioridades
ph1.hilo.setPriority(Thread.NORM_PRIORITY+2);
ph2.hilo.setPriority(Thread.NORM_PRIORITY-2);
//Deje ph3, ph4 y ph5 en el nivel de prioridad normal predeterminado

//Comenzar los hilos


ph1.hilo.start();
ph2.hilo.start();
ph3.hilo.start();
ph4.hilo.start();
ph5.hilo.start();
try {
ph1.hilo.join();
ph2.hilo.join();
ph3.hilo.join();
ph4.hilo.join();
ph5.hilo.join();
}catch (InterruptedException exc){
System.out.println("Hilo principal interrumpido.");
}
System.out.println("\nHilo de alta prioridad contó hasta "+ph1.contar);
System.out.println("Hilo de baja prioridad contó hasta "+ph2.contar);
System.out.println("Hilo de normal prioridad #1 contó hasta "+ph3.contar);
System.out.println("Hilo de normal prioridad #2 contó hasta "+ph4.contar);
System.out.println("Hilo de normal prioridad #3 contó hasta "+ph5.contar);
}
}
El método run() contiene un bucle que cuenta el número de iteraciones.
El ciclo se detiene cuando el conteo llega a 10,000,000 o la variable
estática stop es true. Inicialmente, stop se establece en false, pero el primer hilo
para finalizar los conjuntos de conteo establece stop en true. Esto provoca que
cada hilo termine con su siguiente segmento de tiempo.
Cada vez que se pasa por el ciclo, la cadena nombreActual se compara con el
nombre del hilo que se está ejecutando. Si no coinciden, significa que se produjo
un cambio de tarea. Cada vez que se produce un cambio de tarea, se muestra
el nombre del nuevo hilo y se le asigna al nombreActual el nombre del nuevo
hilo.
La visualización de cada cambio de hilo le permite ver (de forma muy imprecisa)
cuando los hilos obtienen acceso a la CPU. Después de detener los hilos, se
muestra el número de iteraciones para cada ciclo.
Salida:
Hilo de alta prioridad contó hasta 10000000
Hilo de baja prioridad contó hasta 729262
Hilo de normal prioridad #1 contó hasta 9563850
Hilo de normal prioridad #2 contó hasta 4784722
Hilo de normal prioridad #3 contó hasta 9983470
En esta ejecución, el hilo de alta prioridad obtuvo la mayor cantidad de tiempo
de CPU. Por supuesto, la salida exacta producida por este programa dependerá
de una serie de factores, incluida la velocidad de tu CPU, la cantidad de CPU en
tu sistema, el sistema operativo que está utilizando y el número y la naturaleza
de otras tareas que se ejecutan en el sistema. Por lo tanto, es posible que el hilo
de baja prioridad obtenga el mayor tiempo de CPU si las circunstancias son las
correctas.
2.2.3. Sincronización de Hilos

Cuando en un programa tenemos varios hilos corriendo simultáneamente es


posible que varios hilos intenten acceder a la vez a un mismo sitio (un fichero,
una conexión, un array de datos) y es posible que la operación de uno de ellos
entorpezca la del otro. Para evitar estos problemas, hay que sincronizar los hilos.
Por ejemplo, si un hilo con vocación de Cervantes escribe en fichero "El Quijote"
y el otro con vocación de Shakespeare escribe "Hamlet", al final quedarán todas
las letras entremezcladas. Hay que conseguir que uno escriba primero su Quijote
y el otro, luego, su Hamlet.
Sincronizar usando un objeto
Imagina que escribimos en un fichero usando una variable fichero de
tipo PrintWriter. Para escribir uno de los hilos hará esto
fichero.println("En un lugar de la Mancha...");
Mientras que el otro hará esto
fichero.println("... ser o no ser ...");
Si los dos hilos lo hacen a la vez, sin ningún tipo de sincronización, el fichero al
final puede tener esto
En un ... ser lugar de la o no Mancha ser ...
Para evitarlo debemos sincronizar los hilos. Cuando un hilo escribe en el fichero,
debe marcar de alguna manera que el fichero está ocupado. El otro hilo, al
intentar escribir, lo verá ocupado y deberá esperar a que esté libre. En java esto
se hace fácilmente. El código sería así
synchronized (fichero)
{
fichero.println("En un lugar de la Mancha...");
}
y el otro hilo
synchronized (fichero)
{
fichero.println("... ser o no ser ...");
}
Al poner synchronized(fichero) marcamos fichero como ocupado desde que se
abren las llaves de después hasta que se cierran. Cuando el segundo hilo intenta
también su synchronized(fichero), se queda ahí bloqueado, en espera que de
que el primero termine con fichero. Es decir, nuestro hilo Shakespeare se queda
parado esperando en el synchronized(fichero) hasta que nuestro hilo Cervantes
termine.
synchronized comprueba si fichero está o no ocupado. Si está ocupado, se
queda esperando hasta que esté libre. Si está libre o una vez que esté libre, lo
marca como ocupado y sigue el código.
Este mecanismo requiere colaboración entre los hilos. El que hace el código
debe acordarse de poner synchronized siempre que vaya a usar fichero. Si no lo
hace, el mecanismo no sirve de nada.
Métodos sincronizados
Otro mecanismo que ofrece java para sincronizar hilos es usar métodos
sincronizados. Este mecanismo evita además que el que hace el código tenga
que acordarse de poner synchronized.
Imagina que encapsulamos fichero dentro de una clase y que ponemos un
método synchronized para escribir, tal que así
public class ControladorDelFichero
{
private PrintWriter fichero;

public ControladorFichero()
{
// Aqui abrimos el fichero y lo dejamos listo
// para escribir.
}

public synchronized void println(String cadena)


{
fichero.println(cadena);
}
}
Una vez hecho esto, nuestros hilos Cervantes y Shakespeare sólo tienen que
hacer esto
ControladorFichero control = new ControladorFichero();
...
// Hilo Cervantes
control.println("En un lugar de la Mancha ...");
...
// Hilo Shakespeare
control.println("... ser o no ser ...");
Al ser el método println() synchronized, si algún hilo está dentro de él ejecutando
el código, cualquier otro hilo que llame a ese método se quedará bloqueado en
espera de que el primero termine.
Este mecanismo es más mejor porque, siguiendo la filosfía de la orientación a
objetos, encapsula más las cosas. El fichero requiere sincronización, pero ese
conocimiento sólo lo tiene la clase ControladorFichero. Los hilos Cervantes y
Shakespeare no saben nada del tema y simplemente se ocupan de escribir
cuando les viene bien. Tampoco depende de la buena memoria del programador
a la hora de poner el synchronized(fichero) de antes.
Otros objetos que necesitan sincronización
Hemos puesto de ejemplo un fichero, pero requieren sincronización en general
cualquier entrada y salida de datos, como pueden ser ficheros, sockets o incluso
conexiones con bases de datos.
También pueden necesitar sincronización almacenes de datos en memoria,
como LinkedList, ArrayList, etc. Imagina, por ejemplo, en una LinkedList que un
hilo está intentando sacar por pantalla todos los datos
LinkedList lista = new LinkedList();
...
for (int i=0;i<lista.size(); i++)
System.out.println(lista.get(i));
Estupendo y maravilloso pero ... ¿qué pasa si mientras se escriben estos datos
otro hilo borra uno de los elementos?. Imagina que lista.size() nos ha devuelto 3
y justo antes de intentar escribir el elemento 2 (el último) viene otro hilo y borra
cualquiera de los elementos de la lista. Cuando intentemos el lista.get(2) nos
saltará una excepción porque la lista ya no tiene tantos elementos.
La solución es sincronizar la lista mientras la estamos usando
LinkedList lista = new LinkedList();
...
synchronized (lista)
{
for (int i=0;i<lista.size(); i++)
System.out.println(lista.get(i));
}
además, este tipo de sincronización es la que se requiere para mantener
"ocupado" el objeto lista mientras hacemos varias llamadas a sus métodos
(size() y get()), no queda más remedio que hacerla así. Por supuesto, el que
borra también debe preocuparse del synchronized.
2.2.4. Aplicaciones

Los Hilos o los “Threads” en Java, son basicamente una forma de poder ejecutar varios
procesos simultáneamente en nuestros programas en Java.

Usualmente para poder utilizarlos tenemos que crear clases que extienden a la clase
Thread, y reescribir el metodo principal “run()”, el cual es el que se va a ejecutar
principalmente al iniciar un hilo, thread o nuevo proceso en java.

Ejemplo de hilos
Veamos como funcionan los Threads con una aplicación en Java. Vamos a
Netbeans y creamos un proyecto llamado Threads. Insertamos un JFrame y le
colocamos un botón con el que iniciaremos la ejecución se los Threads.

Ahora vamos a programar el botón que colocamos en el JFRame.


Como podemos observar, Netbeans marca 3 errores con la inicialización de los
threads. Esto se debe a que necesitamos implementar la interfaz Runnable en
la Clase de nuestra JFrame.

Aún así Netbeans marca un error. Le damos clic en el ícono de la izquierda


para corregir el error. Nos aparecerá la opción “Implement all abstract
methods”.
Al hacer clic desaparecerá el error. Al final del código se agregará lo siguiente:

En este nuevo método que se ha agregado es donde se coloca el código que


ejecutarán los threads.
Para ver como se ejecutan los threads, veremos una carrera de 3 procesos.
Primero declararemos 3 variables, c1, c2 y c3. Serán del tipo entero y las
inicializaremos en 0.

Estos métodos lo que harán es que le agregarán una unidad a cada una de las
variables, es decir, c1, c2 y c3.

Ahora nos dirigimos al final del programa, donde está el método public void

Esto funciona de la siguiente manera:


La variable ct adoptará el valor del CurrenThread, es decir, el hilo que se esté
ejecutando en determinado instante.
Mientras ese hilo que se esté ejecutando sea el hilo1, se ejecutará la
función corredor1 que es la encargada de aumentar la variable c1. La
función System.out.println(“Corredor 1: ” + c1); imprime el valor de c1 en la
parte inferior de Netbeans IDE.
Se repite el mismo proceso para los otros 2 hilos. Lo que queremos darnos
cuenta es como Java ejecuta el código. Lo hemos colocado uno debajo del
otro, como una secuencia, pero al ejecutar el programa y presionar el botón
nos damos cuenta de que no es una secuencia.
Cuando ejecutamos el programa obtenemos lo siguiente:
Corredor 1: 1
Corredor 1: 2
Corredor 3: 1
Corredor 2: 1
Corredor 3: 2
Corredor 1: 3
Corredor 3: 3
Corredor 2: 2
Corredor 3: 4
Corredor 1: 4
Corredor 3: 5
Corredor 2: 3
Corredor 3: 6
Corredor 1: 5
UNIDAD III APLICACIONES DE CLASES E INTERFACES
INTERNAS

3.1. CLASES INTERNAS

Las clases internas son interesantes porque nos permiten agrupar clases
relacionadas y controlar la visibilidad mutua de esas clases. Sin embargo son
algo totalmente diferente del mecanismo de composición que hemos visto y
tampoco hay que pensar en ellas como una forma de ocultar código: colocamos
clases dentro de otras clases. Una clase interna conoce los detalles de la clase
contenedora y puede comunicarse con ella. Además el tipo de código que puede
escribirse con las clases internas es más elegante y claro (aunque no siempre,
claro).

3.1.1 Definición de Clase

Las clases se utilizan para representar entidades o conceptos, como los


sustantivos en el lenguaje. Cada clase es un modelo que define un conjunto de
variables -el estado, y métodos apropiados para operar con dichos datos -el
comportamiento. Cada objeto creado a partir de la clase se denomina instancia
de la clase.
Los tipos de clases son:
•Class. Public: Son muy comunes, accesibles desde cualquier otra clase en la
misma librería (de otro modo hay que importarlas).
•Class. Abstract: Aquellas que tienen por lo menos un método abstracto. No
implementan sus métodos, sino que dan las bases para que sean
implementados en la herencia.
•Class. Final: Son las que terminan la cadena de herencia. Útiles por motivos
de seguridad y eficiencia de un programa, ya que no permiten crear más sub-
divisiones por debajo de esta clase.
•Class. Synchronizable: Especifica que sus métodos son sincronizados,
evitando problemas con los thread (hilo de ejecución), de forma que estos no
pueden empezar a correr un método si no ha acabado el otro.
3.1.2 Definición de Clase Interna

Una clase interna es una clase definida dentro de otra clase, llamada clase
contenedora, en alguna variante de la siguiente forma general:

class ClaseContenedora {
...
class ClaseInterna {
...
}
...
}
Las clases internas fueron introducidas en la versión Java 1.1.
Además de su utilidad en sí, las clases internas se utilizan mucho en el nuevo
modelo de eventos que se introdujo en dicha versión de Java.

Hay cuatro tipos de clases internas:

1. Clases internas static.


2. Clases internas miembro.
3. Clases internas locales.
4. Clases anónimas.

En lo sucesivo se utilizará la terminología clase contenedora o clase global para


hacer referencia a la clase que contiene a la clase interna.
Hay que señalar que la JVM (Java Virtual Machine) no sabe nada de la existencia
de clases internas.
Por ello, el compilador convierte estas clases en clases globales, contenidas en
ficheros *.class cuyo nombre es ClaseContenedora$ClaseInterna.class. Esta
conversión inserta variables ocultas, métodos y argumentos en los
constructores. De todas formas, lo que más afecta al
programador de todo esto es lo referente al nombre de los ficheros que aparecen
en el directorio donde se realiza la compilación, que pueden resultar
sorprendentes si no se conoce su origen.
// Programa Java para demostrar el acceso a una clase interna

//Clase externa

class ClaseExterna

//Miembro estático

static int externo_x=10;

//Miembro de instancia

int externo_y=20;

//Miembro privado

private int externo_privado=30;

class ClaseInterna{

void mostrar(){

//Puede acceder al miembro estático de la clase externa

System.out.println("externo_x: "+externo_x);

//Puede acceder a un miembro no estático de la clase externa

System.out.println("externo_y: "+externo_y);

//Puede acceder a mostrar un miembro privado de la clase externa

System.out.println("externo_privado: "+externo_privado);

class ClaseInternaDemo{

public static void main(String[] args) {


//Accediendo a la clase interna

ClaseExterna objetoExterno=new ClaseExterna();

ClaseExterna.ClaseInterna objetoInterno= objetoExterno.new


ClaseInterna();

objetoInterno.mostrar();

3.1.3 Aplicación de Clases Internas

A veces, una clase interna se utiliza para proporcionar un conjunto de servicios


que solo utiliza su clase adjunta. Aquí hay un ejemplo que usa una clase
interna para calcular varios valores para su clase adjunta:

Ejemplo:

1. // Programa Java para demostrar las clases internas


2.
3. //Clase externa
4. class ClaseExterna {
5. int nums[];
6.
7. ClaseExterna(int n[]){
8. nums=n;
9. }
10.
11. void analizar(){
12. Interna inOb=new Interna();
13. System.out.println("Minimo: "+inOb.min());
14. System.out.println("Máximo: "+inOb.max());
15. System.out.println("Promedio: "+inOb.promedio());
16. }
17.
18. //Esta es una clase interna
19. class Interna{
20. int min(){
21. int m=nums[0];
22.
23. for (int i=1;i<nums.length;i++)
24. if(nums[i]<m) m= nums[i];
25. return m;
26. }
27.
28. int max(){
29. int m=nums[0];
30. for (int i=1; i<nums.length;i++)
31. if (nums[i]>m) m=nums[i];
32. return m;
33. }
34.
35. int promedio(){
36. int a=0;
37. for (int i=0; i<nums.length;i++)
38. a+=nums[i];
39. return a/nums.length;
40. }
41. }
42. }
43.
44. class ClaseAndidadaDemo {
45. public static void main(String[] args) {
46.
47. int x[]={3,2,1,5,6,7,8,9};
48. ClaseExterna extob= new ClaseExterna(x);
49. extob.analizar();
50.
51. }
52. }
Salida:

Minimo: 1
Máximo: 9
Promedio: 5

En este ejemplo, la clase Interna calcula varios valores de los nums de la


matriz, que es miembro de ClaseExterna. Como se explicó, una clase interna
tiene acceso a los miembros de su clase envolvente, por lo que es
perfectamente aceptable que Interna acceda directamente a la matriz nums.
Por supuesto, lo opuesto no es verdad. Por ejemplo, no sería posible
que analizar() invoque el método min() directamente, sin crear un objeto
interno.
3.2. INTERFACES

3.2.1 Definición de Interfaz

Cuando se habla de Sitios Web, se denomina interfaz al conjunto de elementos


de la pantalla que permiten al usuario realizar acciones sobre el Sitio Web que
está visitando. Por lo mismo, se considera parte de la interfaz a sus elementos
de identificación, de navegación, de contenidos y de acción.
Todos ellos deben estar preparados para ofrecer servicios determinados al
usuario, con el fin de que éste obtenga lo que vino a buscar cuando visitó el Sitio
Web. Por lo anterior, cada uno de los elementos que sean integrados dentro de
la interfaz debe estar pensado para causar un efecto sobre el usuario y deben
ser utilizados con un propósito.
En este sentido, es importante considerar que Jakob Nielsen, uno de los autores
más citados en cuanto a la usabilidad de los Sitios Web, destaca que los
elementos más importantes de la portada de todo Sitio Web se pueden resumir
en cuatro postulados generales:
Dejar claro el propósito del sitio: se refiere a que el sitio debe explicar a quién
pertenece y qué permite hacer a quienes lo visitan; se entiende que debe hacerlo
de manera simple y rápida. Por ejemplo, ayuda en este sentido el cumplimiento
de las normas referidas a uso de URLs y logotipos oficiales.
Ayudar a los usuarios a encontrar lo que necesitan: implica que debe contar con
un sistema de navegación visible y completo, pero que además deberá estar
complementado por algún sistema de búsqueda que sea efectivo para acceder
al contenido al que no se logra acceder o que no se encuentra a simple vista.
Demostrar el contenido del sitio: significa que el contenido se debe mostrar de
manera clara, con títulos comprensibles por parte del usuario y con enlaces hacia
las secciones más usadas que estén disponibles donde el usuario los busque.
Ayudará en este sentido tener un seguimiento de las visitas para comprender
qué es lo más visto y lo más buscado del Sitio Web.
Usar diseño visual para mejorar y no para definir la interacción del Sitio Web: se
refiere a que los elementos gráficos del Sitio Web deben estar preparados para
ayudar en los objetivos del sitio y no sólo como adornos utilizados para rellenar
espacio. Aunque se trata de uno de los temas más debatibles, su alcance no es
el de restringir el uso de imágenes y elementos gráficos, sino a que su uso sea
adecuado para la experiencia de uso que se desea ofrecer.
Como se puede apreciar, el foco central de una interfaz es permitir que el usuario
que llega como visitante logre los objetivos que lo trajeron al Sitio Web y que ésta
le facilite el acceso a los contenidos que están incorporados a través de sus
pantallas.
Para conseguir esto, es necesario que la interfaz adopte los elementos, que
detallamos en este capítulo, a través de los cuales será posible conseguir el
cumplimiento de los postulados antes señalados.
Elementos de la interfaz
La interfaz del Sitio Web, cualquiera sea el objetivo que persiga, debe dar cuenta
de normas de carácter general, que se refieren a sus características como
sistema de información y comunicación. Gracias al cumplimiento de éstas, el
usuario logrará acceder a las informaciones que se le ofrecen y, además, podrá
realizar las acciones que el organismo dueño del espacio digital le entrega a
través de este sistema.
Dichas características tienen que ver con los elementos de identificación, de
navegación, de contenidos y de acción que el Sitio Web debe contener, todos
los cuales se analizan en esta sección.
La existencia e importancia de dichos elementos, como asimismo la ubicación
que deben tener en la interfaz, se ha visto comprobada a través de las
investigaciones que se han hecho en torno a los Sitios Web. Con ellas se
demuestra que las zonas que normalmente se ven en una visita inicial, están
conformadas por una letra F o bien por un triángulo, cuya sección más revisada
es la que se encuentra en la esquina superior izquierda.
Por lo anterior, es importante que las interfaces se construyan tomando en
cuenta esta evidencia, con el fin de asegurar que los visitantes reciban la
información en cuanto lleguen al Sitio Web, permitiendo que el diseño web
contribuya al mejor uso de los contenidos y funcionalidad, en lugar de afectar
dicho uso respecto de los elementos de la interface, los aspectos más relevantes
a tener en consideración son los siguientes usos de logotipos
Sistema de navegación
Áreas de contenidos
Áreas de interacción
Experiencia de usuario

3.2.2 Sintaxis para la Implementacion de Interfaz

Las interfaces de objetos son contratos que han de cumplir las clases que las
implementan. Contienen métodos vacíos que obligan a una clase a emplearlos,
promoviendo así un estándar de desarrollo.
Si una clase implementa una interface, está obligada a usar todos los métodos
de la misma (y los mismos tipos de argumentos de los métodos), de lo contrario
dará un error fatal. Pueden emplearse más de una interface en cada clase, y
pueden extenderse entre ellas mediante extends. Una interface puede extender
una o más interfaces.
Todos los métodos declarados en una interface deben ser públicos.
Para definir una interface se utiliza la parabra interface, y para extenderla se
utiliza implements.
interface Automovil {
public function getTipo();
public function getRuedas();
}
class Coche implements Automovil {
public function getTipo(){
echo "Coche";
}
public function getRuedas(){
echo "4";
}
}
class Moto implements Automovil {
public function getTipo(){
echo "Moto";
}
public function getRuedas(){
echo "2";
}
}
Las clases Coche y Moto están obligadas a definir las
funciones getTipo() y getRuedas(). Así se crea un modelo para todas
las clases de automóviles que deben aportar o definir unos métodos mínimos.
Si por ejemplo getTipo() tuviera un argumento de tipo Array: getTipo(Array
$tipos), las clases que implementen la interface deberán importar un argumento
del mismo tipo.
Las interfaces también pueden definir constantes, que funcionan igual que
las constantes en clases, pero no pueden ser sobreescritas por sus
descendientes, ya sean clases o interfaces.
Se utilizan cuando se tienen muchas clases que tienen en común un
comportamiento, pudiendo asegurar así que ciertos métodos estén disponibles
en cualquiera de los objetos que queramos crear. Son especialmente
importantes para la arquitectura de aplicaciones complejas.

3.2.3 Aplicaciones de Interfaz

Las interfaces son un sistema bastante común, utilizado en programación


orientada a objetos. Son algo así como declaraciones de funcionalidades que
tienen que cubrir las clases que implementan las interfaces.

En una interfaz se definen habitualmente un juego de funciones que deben


codificar las clases que implementan dicha interfaz. De modo que, cuando una
clase implementa una interfaz, podremos estar seguros que en su código están
definidas las funciones que incluía esa interfaz.

A la hora de programar un sistema, podemos contar con objetos que son muy
diferentes y que por tanto no pertenecen a la misma jerarquía de herencia, pero
que deben realizar algunas acciones comunes. Por ejemplo, todos los objetos
con los que comercia unos grandes almacenes deben contar con la
funcionalidad de venderse. Una mesa tiene poco en común con un calefactor o
unas zapatillas, pero todos los productos disponibles deben implementar una
función para poder venderse.

Otro ejemplo. Una bombilla, un coche y un ordenador son clases muy distintas
que no pertenecen al mismo sistema de herencia, pero todas pueden
encenderse y apagarse. En este caso, podríamos construir una interfaz
llamada "encendible", que incluiría las funcionalidades de encender y apagar.
En este caso, la interfaz contendría dos funciones o métodos, uno encender() y
otro apagar().

Cuando se define una interfaz, se declaran una serie de métodos o funciones


sin especificar ningún código fuente asociado. Luego, las clases que
implementen esa interfaz serán las encargadas de proporcionar un código a los
métodos que contiene esa interfaz. Esto es seguro: si una clase implementa
una interfaz, debería declarar todos los métodos de la interfaz. Si no tenemos
código fuente para alguno de esos métodos, por lo menos debemos declararlos
como abstractos y, por tanto, la clase también tendrá que declararse como
abstracta, porque tiene métodos abstractos.

Código para definir una interfaz

Veamos el código para realizar una interfaz. En concreto veremos el código de


la interfaz encendible, que tienen que implementar todas las clases cuyos
objetos se puedan encender y apagar.

interface encendible{
public function encender();
public function apagar();
}
Vemos que para definir una interfaz se utiliza la palabra clave interface,
seguida por el nombre de la interfaz y, entre llaves, el listado de métodos que
tendrá. Los métodos no se deben codificar, sino únicamente declararse.

Implementación de interfaces

Ahora veamos el código para implementar una interfaz en una clase.

class bombilla implements encendible{


public function encender(){
echo "<br>Y la luz se hizo...";
}

public function apagar(){


echo "<br>Estamos a oscuras...";
}
}
Para implementar una interfaz, en la declaración de la clase, se debe utilizar la
palabra implements, seguida del nombre de la interfaz que se va a
implementar. Se podrían implementar varias interfaces en la misma clase, en
cuyo caso se indicarían todos los nombres de las interfaces separadas por
comas.

En el código de la clase estamos obligados a declarar y codificar todos los


métodos de la interfaz.

Ahora veamos el código de la clase coche, que también implementa la interfaz


encendible. Este código lo hemos complicado un poco más.
class coche implements encendible{
private $gasolina;
private $bateria;
private $estado = "apagado";

function __construct(){
$this->gasolina = 0;
$this->bateria = 10;
}

public function encender(){


if ($this->estado == "apagado"){
if ($this->bateria > 0){
if ($this->gasolina > 0){
$this->estado = "encendido";
$this->bateria --;
echo "<br><b>Enciendo...</b> estoy encendido!";
}else{
echo "<br>No tengo gasolina";
}
}else{
echo "<br>No tengo batería";
}
}else{
echo "<br>Ya estaba encendido";
}
}

public function apagar(){


if ($this->estado == "encendido"){
$this->estado = "apagado";
echo "<br><b>Apago...</b> estoy apagado!";
}else{
echo "<br>Ya estaba apagado";
}
}

public function cargar_gasolina($litros){


$this->gasolina += $litros;
echo "<br>Cargados $litros litros";
}
}
A la vista del anterior código, se puede comprobar que no hay mucho en
común entre las clases bombilla y coche. El código para encender una bombilla
era muy simple, pero para poner en marcha un coche tenemos que realizar
otras tareas. Antes tenemos que ver si el coche estaba encendido previamente,
si tiene gasolina y si tiene batería. Por su parte, el método apagar hace una
única comprobación para ver si estaba o no el coche apagado previamente.
UNIDAD IV FUNDAMENTOS DE INTERFACES GRAFICAS DE
USUARIO

4.1. CONCEPTOS BASICOS

Interfaz gráfica de usuario (En inglés Graphic User Interface, también conocido
con su acrónimo GUI) es un método para facilitar la interacción del usuario con
el ordenador o la computadora a través de la utilización de un conjunto de
imágenes y objetos pictóricos (iconos, ventanas..) además de texto. Surge como
evolución de la línea de comandos de los primeros sistemas operativos y es
pieza fundamental en un entorno gráfico.

4.1.1 Definicion de GUI

GUI es un acrónimo del vocablo inglés Graphical User Interface. Douglas


Engelbart, además de inventor del ratón de ordenador, desarrolló la primera
interfaz gráfica en los años 1960 en EE.UU. en los laboratorios de XEROX. Fue
introducida posteriormente al público en las computadoras Apple Macintosh en
1984, y a las masas hasta 1993 con la primera versión popular del sistema
operativo Windows 3.0. Los GUIs que no son PUIs son encontrados en juegos
de computadora, y los GUIs avanzados basados en realidad virtual ahora son
usados con más frecuencia en las investigaciones. Muchos grupos de
investigación en Norteamérica y Europa están trabajando actualmente en el
interfaz de enfoque del usuario o ZUI (Zooming User Interface), que es un
adelanto lógico en los GUI, mezclando 3D con 2.o o "2D y medio objetos
vectoriales de una D".

4.1.2 Elementos Básicos de una GUI

Barra de desplazamiento: La barra de desplazamiento es un elemento de las


interfaces gráficas que constan de una barra horizontal o vertical con dos
extremos con flechas que apuntan en sentidos contrarios y que suelen ubicarse
en los extremos de una ventana o recuadro. Las barras de desplazamiento
permiten desplazar el contenido del cuadro hacia un lado u otro. Las barras
suelen aparecer o activarse cuando el recuadro no es lo suficientemente grande
como para visualizar todo su contenido.

Barra de Estado Elemento: Se encuentra en las interfaces gráficas, que permite


mostrar información acerca del estado actual de la ventana. Generalmente las
barras de estado se ubican en la parte inferior de las ventanas.
Barra de herramientas: Agrupación de íconos con los cuales es posible acceder
a determinadas herramientas o funciones en una aplicación.

Barra de Progreso: Elemento en las interfaces gráficas que permiten mostrar de


forma gráfica el estado de avance de una tarea o proceso.

Barra de Título: Elemento de las interfaces gráficas que se encuentra en la parte


más superior de una ventana, donde aparece un título que se corresponde con
el contenido de la misma.

Botón: En interfaces gráficas de usuario, los botones son tipos de widget que
permiten al usuario comenzar un evento, como buscar, aceptar una tarea,
interactuar con un cuadro de diálogo, etc.

Botón de Opción: Elemento en las interfaces gráficas que permite elegir sólo una
opción de un conjunto predefinido de opciones.

Casillero de Verificación: Interfaz gráfico que permite al usuario marcar múltiples


selecciones de un número de opciones.

Cuadro de Dialogo: En interfaces gráficas de usuario, un cuadro de diálogo es


una ventana especial para mostrar información al usuario o para obtener de éste
una respuesta.

Cuadro de Texto: Un cuadro de texto es un elemento típico en las interfaces


gráficas en donde es posible insertar texto.

Icono: Los íconos del sistema son aquellos íconos que se utilizan para identificar
archivos, accesos directos, programas y herramientas del sistema operativo.

Lista: Una lista es una relación de datos, ordenados o clasificados según su tipo.

Lista Despegable: Tipo de elemento GUI que permite al usuario escribir sobre un
campo de texto mientras se muestra una lista de opciones.

Menú: un menú es una herramienta gráfica en la interfaz de páginas web y


aplicaciones que consiste de una lista de opciones que puede desplegarse para
mostrar más opciones o funciones.

Menú Contextual: En aplicaciones o sistemas operativos, tipo de menú que se


adaptará al contexto desde donde se accede. El menú contextual se accedo con
el clic derecho sobre algún elemento en la pantalla.

Menú Despegable: Elemento GUI que permite a un usuario seleccionar de una


lista desplegable una opción. Se distingue de una simple lista en el hecho de que
el usuario debe presionar sobre el menú para que se muestren las opciones
disponibles.
Panel Lateral: Elemento usado en las interfaces gráficas que permiten mostrar
diferentes formas de información en un lado de una aplicación o el escritorio.

Pestaña: Elemento que se encuentra en las interfaces gráficas, que permite


cambiar entre distintos documentos o secciones de forma rápida.

Slider: Un slider es un elemento de las interfaces gráficas que permiten


seleccionar un valor moviendo un indicador o, en algunos casos, el usuario
puede hacer clic sobre algún punto del slider para cambiar hacia ese valor.

4.2 IMPLEMENTACION

4.2.1 Implementacion De Una GUI En Java

Hay muchas herramientas disponibles con las que los diseñadores pueden
crear la totalidad de las GUI. Algunas herramientas se pueden incorporar en en
entorno software(IDE).

La implementación de las herramientas de la GUI ofrece un poderoso


despliegue de controles de GUI. Para la customización del software
customization, los diseñadores pueden cambiar el código en acorde.

Hay distintos segmentos de las herramientas GUI según su uso y su plataforma.


Ejemplo

GUI para móvil, para ordenador, para pantalla táctil, etc. Aquí se enumeran
algunas herramientas útiles para la construcción de una GUI:

 FLUID
 AppInventor (Android)
 LucidChart
 Wavemaker
 Visual Studio

Llamamos Interfaz Gráfica GUI (Graphical User Interface) al conjunto de


componentes gráficos que posibilitan la interacción entre el usuario y la
aplicación. Es decir ventnas, botones, combos, listas, cajas de diálogo, campos
de texto, etc.
Primero tenemos que diseñar la aplicación,programarla y por último los eventos
que se generan a medida que el usuario interactua con la Interfaz.

Los componentes son objetos de las clases que heredan de la clase


base componente como Button, List, TextField, TextArea, Label, etc.

En una GUI los componentes son contenidos en Contenedores o containers. Un


Containes es un objeto cuya clase hereda de Container(clase que a su vez es
subclase de Component) y tiene la responsabilidad de contener Componentes.

Generalmente una GUI se monta sobre un Frame. Esté sera el Container


principal que contendrá a los componentes de la Interfaz Gráfica, un Container
podría contener a otros containers.

Distribución de componentes (layouts)

Los containers contienen componentes y estos son acomodados dentro del


espacio visual del container respetanto unaa cierta distribución que llamaremos
layout.

AWT y Swing

Java provee dos API's con las que podemos trabajar para desarrollar GUIs, la
más básica es AWT (Abstrct Window Toolkit). Las más desarrolladas se hacen
con Swing, las cuales son más identificables ya que todas comienzan con "J",
por ejemplo: JButton, JTextField, JTextArea, JPanel y JFrame son clases de
Swing.

Todo el manejo de eventos y layouts es exactamente el mismo para AWT y


Swing.

Distribuciones Relativas

Los layouts determinan el criterio con el que se vaan a distribuir los componentes
dentro del container
FlowLayout : Distribuye los componentes uno al lado del otro en la parte superior
del container. Por defecto provee una alineación centrada, pero también puede
alinear a la izquierda o derecha.

BorderLayout: Divide el espacio del container en 5 regiones: NORTH, SOUTH,


EAST, WEST y CENTER, admite un único componente por región

GridLayout: Divide el espacio del container en una grilla de n filas por m


columnas, en donde las celdas son de igual tamaño

GridBagLayout: Divide el espacio del container en una grilla donde cada


componente puede ocupar varias filas y columnas. Además permite distribuir el
espacio interno de cada celda.

FlowLayout

Empezaremos con un ejercicio:


La clase Frame nos presenta la típica ventana de Windows, en el código
podemos ver que la clase Ventana1 extiende a Frame por lo tanto Ventana1 es
un Frame y hereda de ésta clase los
métodos setLayout, add, setSize y setVisible

En el constructor definimos cuál sera el layout que queremos utilizar en la


ventana. en este caso utilizamos un FlowLayout, cuya política para distribuir los
componentes es centrarlos en la parte superior del container, pero podemos
cambiar la alineación de los mismos al momento de instanciarlos

Veamos como podemos alinearlos a la izquierda:


BorderLayout

Este layout divide el espacio del container en cinco renglones o bordes y una
region central. Admite sólo un componente por región, por lo tanto un container
con esta distribución sólo podrá contener a lo sumo cinco componentes.
GridLayout

Divide el espacio del container en una grilla de n filas por m columnasdonde


todas las celdas tienenexactamente la misma dimensión
4.2.2 Implementacion De Una GUI En C#

Una interfaz contiene las definiciones de un grupo de funcionalidades


relacionadas que una clase o una estructura pueden implementar.
Mediante las interfaces puede incluir, por ejemplo, un comportamiento de varios
orígenes en una clase. Esta capacidad es importante en C# porque el lenguaje
no admite la herencia múltiple de clases. Además, debe usar una interfaz si
desea simular la herencia de estructuras, porque no pueden heredar de otra
estructura o clase.
Defina una interfaz mediante la palabra clave interface, como se muestra en el
ejemplo siguiente.
C#Copiar
interface IEquatable<T>
{
bool Equals(T obj);
}
El nombre de la estructura debe ser un nombre de identificador de C# válido. Por
convención, los nombres de interfaz comienzan con una letra I mayúscula.
Cualquier clase o estructura que implementa la interfaz IEquatable<T> debe
contener una definición para un método Equals que coincida con la firma que la
interfaz especifica. Como resultado, puede contar con una clase que
implementa IEquatable<T> para contener un método Equals con el que una
instancia de la clase puede determinar si es igual a otra instancia de la misma
clase.
La definición de IEquatable<T> no proporciona una implementación
para Equals. La interfaz define solo la firma. De esa manera, una interfaz en C#
es similar a una clase abstracta en la que todos los métodos son abstractos. Sin
embargo, una clase o estructura puede implementar varias interfaces, pero una
clase solo puede heredar una clase única, ya sea abstracta o no. Por tanto,
mediante las interfaces, puede incluir un comportamiento de varios orígenes en
una clase.
Para obtener más información sobre las clases abstractas, vea Clases y
miembros de clase abstractos y sellados .
Las interfaces pueden contener métodos, propiedades, eventos, indizadores o
cualquier combinación de estos cuatro tipos de miembros. Para obtener vínculos
a ejemplos, vea Secciones relacionadas. Una interfaz no puede contener
constantes, campos, operadores, constructores de instancias, finalizadores ni
tipos. Los miembros de interfaz son públicos automáticamente y no pueden
incluir modificadores de acceso. Los miembros tampoco pueden ser estáticos.
Para implementar un miembro de interfaz, el miembro correspondiente de la
clase de implementación debe ser público, no estático y tener el mismo nombre
y firma que el miembro de interfaz.
Cuando una clase o estructura implementa una interfaz, la clase o estructura
debe proporcionar una implementación para todos los miembros que define la
interfaz. La propia interfaz no proporciona ninguna funcionalidad que una clase
o estructura puedan heredar de la misma la forma en que pueden heredar la
funcionalidad de la clase base. Sin embargo, si una clase base implementa una
interfaz, cualquier clase que se derive de la clase base hereda esta
implementación.
En el siguiente ejemplo se muestra una implementación de la
interfaz IEquatable<T>. La clase de implementación Car debe proporcionar una
implementación del método Equals.
C#Copiar
public class Car : IEquatable<Car>
{
public string Make {get; set;}
public string Model { get; set; }
public string Year { get; set; }

// Implementation of IEquatable<T> interface


public bool Equals(Car car)
{
return this.Make == car.Make &&
this.Model == car.Model &&
this.Year == car.Year;
}
}
Las propiedades y los indizadores de una clase pueden definir descriptores de
acceso adicionales para una propiedad o indizador que estén definidos en una
interfaz. Por ejemplo, una interfaz puede declarar una propiedad que tenga un
descriptor de acceso get. La clase que implementa la interfaz puede declarar la
misma propiedad con un descriptor de acceso get y set. Sin embargo, si la
propiedad o el indizador usan una implementación explícita, los descriptores de
acceso deben coincidir. Para obtener más información sobre la implementación
explícita, vea Implementación de interfaz explícita y Propiedades de interfaces.
Las interfaces pueden heredar de otras interfaces. Una clase puede incluir una
interfaz varias veces mediante las clases base que hereda o mediante las
interfaces que otras interfaces heredan. Sin embargo, la clase puede
proporcionar una implementación de una interfaz solo una vez y solo si la clase
declara la interfaz como parte de la definición de la clase (class ClassName :
InterfaceName). Si la interfaz se hereda porque se heredó una clase base que
implementa la interfaz, la clase base proporciona la implementación de los
miembros de la interfaz. Sin embargo, la clase derivada puede volver a
implementar cualquier miembro de la interfaz virtual, en lugar de usar la
implementación heredada.
Una clase base también puede implementar miembros de interfaz mediante el
uso de los miembros virtuales. En ese caso, una clase derivada puede cambiar
el comportamiento de la interfaz reemplazando los miembros virtuales. Para
obtener más información sobre los miembros virtuales, vea Polimorfismo.
UNIDAD V MAPEO OBJETO RELACIONAL

5.1. CONCEPTOS BASICOS

El mapeo objeto-relacional (más conocido por su nombre en inglés, Object-


Relational mapping, o sus siglas O/RM, ORM, y O/R mapping) es una técnica de
programación para convertir datos entre el sistema de tipos utilizado en
un lenguaje de programación orientado a objetos y la utilización de una base de
datos relacional como motor de persistencia. En la práctica esto crea una base
de datos orientada a objetos virtual, sobre la base de datos relacional. Esto
posibilita el uso de las características propias de la orientación a objetos
(básicamente herencia y polimorfismo). Hay paquetes comerciales y de uso libre
disponibles que desarrollan el mapeo relacional de objetos, aunque algunos
programadores prefieren crear sus propias herramientas ORM.

5.1.1 Justificación del Mapeo Objeto-Relacional

Hoy hablamos del Mapeo Objeto-Relacional o como se conocen


comúnmente, ORM (del inglés Object Relational Mapping). Algunos de vosotros
ya sabréis que son pero, para aquellos que no los conozcan, un ORM te permite
convertir los datos de tus objectos en un formato correcto para poder guardar la
información en una base de datos (mapeo) creándose una base de datos
virtualdonde los datos que se encuentran en nuestra aplicación,
quedan vinculados a la base de datos (persistencia).
Si alguna vez has programado alguna aplicación que se conecta a una base de
datos, habrás podido comprobar lo laborioso que es transformar toda la
información que recibes de la base datos, principalmente en tablas, en los
objetos de tu aplicación y viceversa. A ésto se le denomina mapeo. Utilizando un
ORM este mapeo será automático, es más, será independiente de la base de
datos que estés utilizando en ese momento pudiendo cambiar de motor de base
de datos según tus necesidades.Veamos un ejemplo. Supongamos que tenemos
una tabla de clientes. En nuestra aplicación queremos hacer las funciones
básicas sobre base de datos CRUD (del inglés Create, Read, Update and
Delete) Crear, Obtener, Actualizar y Borrar. Cada operación corresponde con
una sentencia SQL.
Creear: INSERT
Obtener: SELECT
Actualizar: UPDATE
Borrar: DELETE
Si queremos insertar un cliente nuevo y no utilizamos un ORM, el código
quedaría de la siguiente manera si utilizamos C#:
1
String query = "INSERT INTO clientes (id,nombre,email,pais) VALUES (@id,
2
@nombre, @email, @pais)";
3
command.Parameters.AddWithValue("@id","1")
4
command.Parameters.AddWithValue("@nombre","nombre")
5
command.Parameters.AddWithValue("@email","email")
6
command.Parameters.AddWithValue("@pais","pais")
7
command.ExecuteNonQuery();
8

En cambio si utilizamos un ORM, el código se puede reducir de la siguiente


manera:

1 var cliente = new Cliente();


2 cliente.Id = "1";
3 cliente.Nombre = "nombre";
4 cliente.Email = "email";
5 cliente.Pais = "pais";
6 session.Save(customer);

Como podéis comprobar se ha reducido considerablemente el código. Pero lo


más importante de todo, bajo mi punto de vista, es que, imaginaros que
ahora modificamos la tabla de nuestra base de datos y añadimos un campo más
como por ejemplo el apellido de nuestro cliente. En los dos casos, tendríamos
que añadir a nuestra clase Cliente la propiedad correspondiente al apellido pero,
si no utilizas un ORM te tocará revisarte todas las sentencias INSERT, SELECT
y UPDATE para introducir dicho campo en cada una de ellas. En cambio si
utilizas un ORM , lo único que tendrás que hacer será añadir la propiedad a la
clase correspondiente. La sentencia save seguirá siendo la misma, el ORM se
encargará de modificar los INSERT, SELECT y UPDATE por ti. Esto se cumple
hasta cierto punto. Hay algún ORM como MyBatis, que utiliza un híbrido entre
los dos mundos. En MyBatis, las sentencias SQL están escritas en archivos
XML. Esto implica que si modificas la base de datos, también tendrás que
modificar las sentencias del XML correspondiente.
Además de lo que hemos visto hasta el momento, gracias a los ORM
nos abstraemos del motor de base de datos que estamos utilizando es decir, si
en algún momento queremos cambiar de base de datos, nos
resultará sumamente sencillo. En algunos casos con solo cambiar un par de
líneas de código, estaremos cambiando de motor de base de datos.
Existen varios ORM en el mercado. Todo dependerá del lenguaje de
programación que estemos utilizando y de nuestras necesidades. A continuación
podemos ver los ORM para algunos lenguajes de programación:
Hibernate (Java)
MyBatis (Java)
Ebean (Java)
Entity Famework (.NET)
NHibernate (.NET)
MyBatis.NET (.NET)
Doctrine (PHP)
Propel (PHP)
Rocks (PHP)
Torpor (PHP)

5.1.2 Alternativa al Mapeo Objeto-Relacional

En la actualidad hay grandes alternativas de proveedores para el desarrollo de


software, la importancia que cobra los ORM tipo OPEN SOURCE es la facilidad
de implementación de esta herramienta permitiendo tomar como base un modelo
de software terminado para transformarlo a un nuevo y mejor producto. Uno de
los principales inconvenientes encontrados para el estudio de esta temática, es
la poca existencia de fuentes de información en dónde explique lo que involucra
este tópico en el mundo del software. Es por esta razón que el principal objetivo
de este trabajo de investigación es brindar a los estudiantes, docentes y
profesionales del área del desarrollo software, una herramienta que sirva de guía
en el estudio e implementación de los sistemas de mapeo objeto relacional tipo
Open Source.
En el mercado podemos encontrar diversas herramientas tanto de pago como
de uso libre. Algunos programadores, prefieren invertir tiempo en desarrollar su
propia herramienta ORM usando patrones de diseño bien conocidos como son
el Repository o el Active Record.
El patrón Repository se soporta sobre la definición de un repositorio para separar
la lógica que recupera los datos de la base de datos de la lógica de negocio
basada en objetos. Este repositorio hace de puente entre los datos y las
operaciones basadas en objetos, eliminando dependencias tecnológicas y
facilitando el acceso a datos de cualquier tipo.
Por otro lado, está el patrón Active Record. Es un patrón en el cual, el objeto
contiene los datos que representan a un registro de nuestra tabla o vista
relacional, además de encapsular la lógica necesaria para acceder a la base de
datos. De esta forma el acceso a datos se presenta de manera uniforme a través
de la aplicación (lógica de negocio + acceso a datos en una misma clase).
Las herramientas ORM que hay en el mercado son diversas. Algunas están
ligadas al lenguaje de programación orientado a objetos específico.
Algunos ejemplos específicos serían:
Para Java: Hibérnate, iBatis, Ebean, Torque
Para .Net: nHibernate, Entity Framework, DataObjects.NET
Para PHP: Doctrine, Propel , Torpor
Para Python: SQLObject, Django, Tryton
Como resumen al post de hoy, diremos que le uso de herramientas ORM puede
ser una buena solución en el desarrollo de aplicaciones en lenguajes de
programación orientados a objetos ya que ayuda a trasladar el modelo orientado
a objectos al modelo relacional, evitando el uso de sentencias SQL embebidas
en el código de la aplicación.
Sin embargo, si las aplicaciones a desarrollar vana atener gran carga de acceso
a datos o requieren tiempos de respuesta mínimos, este tipo de herramientas no
serían idóneas, ya que penalizarían el rendimiento.
Si eres un desarrollador y tienes experiencia en el uso de este tipo de
herramientas, nos interesaría conocer tus experiencias y cuándo recomendarías
el uso de estas.
5.2 Implementación

El Mapeo Objeto-Relacional es un técnica usada en programación para convertir


los tipos de dato con los que trabaja un lenguaje orientado a objetos a tipos de
dato con los que trabaja un sistema de base de datos relacional para la
persistencia de datos. Básicamente consiste en una técnica que nos permite
mapear cada una de las filas de nuestras tablas en la base de datos a objetos,
en donde las columnas de la tabla corresponden a las propiedades de estos
objetos.
Mientras que ORM es el nombre de la técnica, también se suele conocer como
ORMs a los frameworks que la implementan, como EntityFramework en .NET,
Hibernate en Java y ActiveRecord en Ruby. Estos ORMs usan convenciones de
nombres, archivos de configuración en XML o anotaciones dentro del código
para configurar la relación que existe entre una clase de nuestro lenguaje
orientado a objetos y una tabla en la base de datos.
El uso de una herramienta de ORM introduce una capa de abstracción entre la
base de datos y el desarrollador, ya que gracias a este mapeo, los ORM evitan
que el desarrollador tenga que escribir consultas “a mano” para recuperar, filtrar,
agrupar, eliminar, actualizar o insertar datos en la base, será tarea del ORM
transformar las operaciones hechas a nivel orientado a objetos a sentencias SQL
con las que la base de datos puede trabajar.
Ventajas
Entre las ventajas de los ORMs tenemos que para ellos es necesario escribir
muy poco código, ya que no tenemos que escribir las consultas directamente en
nuestro código o en procedimientos almacenados, ni es nuestra tarea escribir los
métodos que tomen los datos de la base y convertirlos nosotros mismos a algo
procesable en nuestro lenguaje.
Otra ventaja de una herramienta de este tipo es que otorga además la posibilidad
de cambiar el sistema de base de datos sin tener que modificar el código de
nuestra aplicación, ya que bastaría con cambiar la parte del ORM que se conecta
a la base de datos y transforma las operaciones para esta. Generalmente estas
herramientas, los ORMs, tienen módulos intercambiables conocidos como
conectores o adaptadores, quienes son los encargados de realizar esta tarea.
Algunos ORM pueden intentar mejorar el desempeño mediante dos formas:
Empleando un sistema de caché para reducir el número de consultas a la base
de datos para tablas o registros muy solicitados y,
A través de la carga retrasada, lo cual significa que únicamente recuperará la
información de la base de datos cuando la necesitemos
Estas dos características a pesar de que que están diseñadas para
beneficiarnos, si no entendemos correctamente su uso, pueden convertirse en
una desventaja.
Desventajas
Los ORM destacan por su utilidad cuando de desarrollar aplicaciones sencillas
que solo requieren de realizar operaciones básicas: crear, leer, actualizar y
eliminar. Y comienzan a mostrar sus flaquezas cuando de realizar operaciones
más complejas se trata. Y es que los ORM tienden a ser muy genéricos pues
ese es su propósito, tratar de realizar consultas más complejas u operaciones
que requieran de operaciones específicas de la base de datos es llevarlos al
límite.
También es necesario decir que el uso de un ORM puede llegar a impactar en el
desempeño, a diferencia de usar otros métodos de acceso en los que el
desarrollador puede priorizar el desempeño de acuerdo a lo que está
desarrollando.

5.2.1 Uso de motores de Persistencia

Es generalmente sabido que una aplicación informática consta de dos


componentes principales que colaboran para llevar a cabo la funcionalidad que
el usuario desea. El primero de estos componentes es la base de datos, que
guarda la información necesaria para operar la aplicación, en forma de datos
en disco. El segundo de estos componentes es el programa propiamente dicho,
que recupera esos datos de la base de datos, realiza los cálculos necesarios y
presenta los resultados deseados al usuario.
Para que estos dos componentes puedan funcionar juntos deben poder
comunicarse intercambiando datos, como se observa en la figura 1. En otras
palabras, deben ser compatibles. Sin embargo, durante los últimos treinta años
la evolución de estos dos componentes ha sido divergente, de forma que cada
vez se ha hecho más difícil que colaboren en una misma aplicación.
Así, desde los años 70 a la actualidad, las bases de datos utilizan un modelo
teórico llamado “relacional”, que se ha convertido en un estándar y que es
utilizado en la práctica totalidad de aplicaciones de software.
En cambio, los programas han usado, desde los años 80, un modelo llamado
“orientado a objetos”, que difiere en mucho del modelo relacional y que se ha
extendido cada vez más. Es por ello que aparece un conflicto a la hora de
reunir estos dos componentes en una aplicación, ya que cada uno responde a
diferente modelo y forma de operar. Cada componente maneja los datos con
un formato diferente. Metafóricamente, podríamos afirmar que el programa y la
base de datos hablan idiomas diferentes y, por lo tanto, la comunicación entre
ellos resulta difícil.
Este artículo comienza con una descripción de los dos modelos mencionados y
de las diferencias que dificultan su combinación en una sola aplicación. A
continuación, se exploran las diferentes soluciones a este problema y se acaba
concluyendo que la mejor manera de resolverlo es usando un motor de
persistencia. El artículo finaliza indicando los nombres de los motores de
persistencia más usados, con el fin de que el lector pueda elegir el que más se
adapta a sus necesidades.
ANEXOS
USO DE INTERFAZ GRAFICA EN YII2

Modelo vista controlador

Creación de los modelos a utilizar

1.2 Creación de las vistas


1.3 Vista de los modelos creados

APLICACIÓN DE INTERFAZ

1.4 Roles de usuario


1.5 Asignacion de Permisos para cada Usuario

1.6 Creacion de los Roles y Permisos en el modelo vista controlador.


1.7 Creación del rolles

1.8 Rolles
1.9 Creacion de Permisos

1.10 Creacion de un nuevo permiso


1.11 Asignacion de los permisos al Roll.

1.12 Acceso a la interfaz de usuario con los permisos asginados


IMPLEMENTACION DE LAS INTERFACES

1.13 Inplementacion de la base de datos

1.14 Elaboracion de la Base de Datos.


1.15 Elaboracion de la base de datos

1.16 Base de Datos del Sistema


1.17 Elaboracion de reportes mediante la interfaz grafica de usuario

Você também pode gostar