Encapsulamiento y Relaciones entre Objetos
Protegiendo el Estado y Modelando Colaboraciones
En el capítulo anterior (Fundamentos de la Programación Orientada a Objetos) nos enfocamos en el análisis conceptual de un dominio: utilizamos La Heurística Lingüística para identificar objetos a partir de sustantivos, definir su comportamiento a partir de verbos, y aplicar los El Filtro de Abstracción y El Filtro de Complejidad: ¿Valor simple o Clase nueva? para refinar el modelo.
En este capítulo profundizamos en dos conceptos fundamentales de OOP:
Encapsulamiento: El principio de proteger el estado interno de los objetos
Relaciones: Cómo los objetos colaboran entre sí (Asociación, Composición, Agregación)
Encapsulamiento: Protegiendo el Estado¶
¿Qué es el Encapsulamiento?¶
El encapsulamiento es uno de los cuatro pilares fundamentales de la Programación Orientada a Objetos (junto con herencia, polimorfismo y abstracción). Se trata del principio de ocultar los detalles internos de un objeto y exponer únicamente lo necesario para que otros objetos interactúen con él.
Analogía: El Control Remoto¶
Considerá un control remoto de televisión:
Estado interno oculto: Circuitos, baterías, chips, señales infrarrojas
Interfaz pública: Botones claramente etiquetados (volumen, canal, encendido)
No necesitás conocer cómo funcionan los circuitos internos para usar el control. Los botones son la interfaz pública que te permite interactuar con la funcionalidad sin acceder directamente al estado interno.
Del mismo modo, un objeto bien encapsulado:
Oculta sus datos internos (atributos privados)
Expone métodos públicos que permiten interactuar con él de forma controlada
Fusión de Datos y Comportamiento¶
El primer aspecto del encapsulamiento es la fusión de datos y comportamiento en una misma unidad. En el paradigma estructurado, datos y funciones están separados; en POO, están unificados en el objeto.
Comparación visual:
Figure 1:Comparación entre el paradigma estructurado (datos y funciones separados) y el paradigma orientado a objetos (unificados en una sola unidad).
Esta fusión tiene consecuencias profundas:
Los datos conocen sus operaciones: No hay funciones “sueltas” que operen sobre datos ajenos
Cohesión alta: Todo lo relacionado con una responsabilidad está en un solo lugar
Menor acoplamiento: No hay dependencias globales a funciones externas
Ocultamiento de Información¶
El segundo aspecto del encapsulamiento es igualmente fundamental: ocultar los detalles de implementación.
Analogía Extendida: El Televisor
Cuando usás un televisor, interactuás con él a través de una interfaz simple: botones de encendido, volumen, canales. No necesitás saber:
Cómo funciona el circuito interno
Qué señales electrónicas se procesan
Cómo se iluminan los píxeles
El televisor oculta toda esa complejidad y te expone solo lo que necesitás para usarlo. Si el fabricante cambia la tecnología interna (de LCD a OLED, por ejemplo), tu forma de usar el televisor no cambia.
Figure 2:El encapsulamiento en un televisor: la interfaz pública oculta la complejidad de la implementación interna.
¿Por Qué Encapsular?¶
El encapsulamiento no es una restricción arbitraria; tiene beneficios concretos y medibles en el desarrollo de software.
1. Control de Invariantes¶
Una invariante es una condición que debe mantenerse siempre verdadera durante toda la vida del objeto.
Ejemplo: Cuenta Bancaria
Clase: CuentaBancaria
Invariante: El saldo nunca debe ser negativoSi permitimos acceso directo al atributo saldo, cualquier parte del código podría violarlo:
// Mal diseño (sin encapsulamiento)
cuenta.saldo = -1000; // ❌ Viola la invarianteCon encapsulamiento, el objeto controla cómo se modifica el saldo:
// Buen diseño (con encapsulamiento)
cuenta.retirar(1500); // ✓ El método verifica que haya fondosEl método retirar() puede validar:
Si hay saldo suficiente
Si el monto es positivo
Si la cuenta no está bloqueada
2. Facilita el Mantenimiento¶
Cuando el estado es privado, podés cambiar la representación interna sin afectar al código que usa la clase.
Ejemplo: Representación de Fecha
Podríamos almacenar una fecha de dos formas diferentes:
Versión 1:
Atributos: dia, mes, anioVersión 2:
Atributo: timestampUnix (long)Si exponemos métodos públicos (obtenerAnio(), obtenerMes(), etc.), podemos cambiar de Versión 1 a Versión 2 sin que nadie que use la clase lo note.
3. Reduce el Acoplamiento¶
El acoplamiento mide cuánto depende una clase de los detalles internos de otra.
Alto acoplamiento (malo): Código frágil, cambios en cascada
Bajo acoplamiento (bueno): Código modular, cambios localizados
El encapsulamiento reduce el acoplamiento porque las clases solo dependen de interfaces públicas, no de detalles internos.
4. Seguridad y Consistencia¶
Al controlar el acceso al estado, garantizamos que:
Los datos se modifican solo de formas válidas
No se crean estados inconsistentes o ilegales
Se pueden aplicar reglas de negocio en un solo lugar
Ejemplo Completo: Termostato¶
Para consolidar los conceptos de encapsulamiento, analicemos un ejemplo más completo.
Escenario: Un termostato inteligente que controla la temperatura de una habitación.
Invariantes del termostato:
La temperatura objetivo debe estar entre 15°C y 30°C
El modo solo puede ser “calefacción”, “refrigeración” o “apagado”
Si el termostato está apagado, no puede estar calentando ni enfriando
Sin encapsulamiento (mal diseño):
Termostato {
temperaturaObjetivo: 25 // Cualquiera podría poner -100
modo: "calefacción" // Cualquiera podría poner "hola"
estaActivo: true // Inconsistente con modo "apagado"
}
// Código externo puede hacer:
termostato.temperaturaObjetivo = -50; // ❌ Viola invariante 1
termostato.modo = "explosión"; // ❌ Viola invariante 2
termostato.modo = "apagado";
termostato.estaActivo = true; // ❌ Viola invariante 3Con encapsulamiento (buen diseño):
Beneficios observados:
| Aspecto | Sin encapsulamiento | Con encapsulamiento |
|---|---|---|
| Validación | No hay | Cada método valida |
| Consistencia | Puede romperse | Siempre garantizada |
| Cambios futuros | Afectan a todos | Localizados en la clase |
| Responsabilidad | Del usuario | Del objeto |
Relaciones entre Objetos¶
En sistemas orientados a objetos, raramente los objetos existen de forma aislada. Los objetos colaboran para resolver problemas complejos, y estas colaboraciones se modelan mediante relaciones.
Notación UML y Cardinalidad¶
El Lenguaje de Modelado Unificado (UML, Unified Modeling Language) proporciona una notación gráfica estándar para representar relaciones entre clases.
Representación de Asociaciones¶
En UML, una asociación se representa como una línea que conecta dos clases. La línea puede tener:
Nombre de la relación (opcional): Describe la naturaleza de la asociación
Cardinalidad en cada extremo: Indica cuántas instancias participan
Roles (opcional): Nombres que las clases tienen en el contexto de la relación
Ejemplo básico:
Figure 3:Ejemplo de asociación básica entre una Persona y su Dirección.
Esto se lee: “Una Persona vive en una Dirección”.
Cardinalidad (Multiplicidad)¶
La cardinalidad especifica cuántas instancias de una clase pueden estar relacionadas con instancias de otra clase. Se anota en los extremos de la línea de asociación.
Table 1:Notaciones de cardinalidad
| Notación | Significado | Ejemplo |
|---|---|---|
1 | Exactamente uno | Una persona tiene exactamente un DNI |
0..1 | Cero o uno (opcional) | Un empleado tiene 0 o 1 cónyuge registrado |
* o 0..* | Cero o más | Una empresa tiene cero o más empleados |
1..* | Uno o más | Un auto tiene uno o más neumáticos |
n..m | Entre n y m | Un curso tiene entre 5 y 40 estudiantes |
Ejemplo con cardinalidad:
Figure 4:Asociación con cardinalidad: una empresa emplea a cero o más empleados.
Se lee: “Una Empresa (1) emplea a cero o más (*) Empleados”.
Cómo Leer la Cardinalidad¶
La cardinalidad se lee desde el otro extremo de la relación:
Figure 5:Cómo interpretar las cardinalidades en una asociación entre dos clases A y B.
Desde A hacia B: Cada instancia de A está relacionada con
cardYinstancias de BDesde B hacia A: Cada instancia de B está relacionada con
cardXinstancias de A
Ejemplo práctico:
Figure 6:Relación muchos a muchos: un autor escribe uno o más libros, y un libro puede tener varios autores.
Un Autor escribe 1 o más Libros
Un Libro es escrito por 1 o más Autores (coautoría)
Tipos de Relaciones¶
Existen tres tipos principales de relaciones entre objetos, cada una con semántica diferente:
Asociación: Relación general, conexión débil
Composición: Relación fuerte, el todo “contiene” las partes
Agregación: Relación débil, el contenedor agrupa elementos
Asociación¶
La asociación es la relación más general entre dos clases. Indica que existe alguna conexión o conocimiento entre ellas, pero no implica propiedad ni ciclo de vida compartido.
Características de la Asociación¶
Independencia de ciclo de vida: Los objetos pueden existir independientemente
Relación semántica: Expresa conocimiento, uso o colaboración
Puede ser bidireccional o unidireccional
Ejemplos de asociación:
Estudiante–Curso: Un estudiante se inscribe en cursosMedico–Paciente: Un médico atiende a pacientesCliente–Pedido: Un cliente realiza pedidos
Notación UML¶
Línea simple sin decoración especial.
Ejemplo:
Figure 7:Asociación entre Persona y Pasaporte: una persona puede tener o no un pasaporte.
Una persona puede tener 0 o 1 pasaporte. El pasaporte puede existir antes de ser asignado a una persona.
Direccionalidad de la Asociación¶
Las asociaciones pueden ser:
Unidireccional: Solo una clase conoce a la otra.
Figure 8:Asociación unidireccional: el Pedido conoce sus Productos, pero no viceversa.
El pedido conoce qué productos contiene, pero el producto no sabe en qué pedidos está.
Bidireccional: Ambas clases se conocen mutuamente.
Figure 9:Asociación bidireccional: tanto el Estudiante como el Curso se conocen mutuamente.
El estudiante sabe en qué cursos está inscripto, y el curso sabe qué estudiantes tiene.
Composición¶
La composición es una relación fuerte de tipo “tiene-un” donde:
El todo (contenedor) es responsable del ciclo de vida de las partes
Las partes no tienen sentido fuera del contexto del todo
Si se destruye el todo, se destruyen las partes
Analogía: El Auto y su Motor¶
Un auto está compuesto por un motor, ruedas, carrocería, etc.
Si destruís el auto (lo desarmás completamente), el motor ya no es “motor de ese auto”
El motor fue creado para ese auto específico
No tiene sentido hablar del motor sin hablar del auto
Representación UML¶
La composición se representa con un diamante relleno (♦) en el extremo del contenedor:
Figure 10:Composición en un automóvil: las partes (motor, carrocería, ruedas) pertenecen exclusivamente al auto.
El diamante negro indica propiedad fuerte.
Características de la Composición¶
Ciclo de vida dependiente: Cuando se destruye el todo, se destruyen las partes
Creación por el contenedor: El todo típicamente crea las partes en su constructor
Cardinalidad del todo: Una parte pertenece a exactamente un todo
Semántica fuerte: “No puede existir sin”
Ejemplos de composición:
Universidad♦─Facultad: Las facultades existen porque existe la universidadLibro♦─Pagina: Las páginas son parte integral del libroCasa♦─Habitacion: Las habitaciones no existen fuera de la casa
Ejemplo Detallado: Factura y Líneas de Detalle¶
Una factura está compuesta por líneas de detalle:
¿Por qué es composición?
Las líneas de detalle no existen sin la factura — no tiene sentido una línea suelta
La factura crea las líneas cuando se agregan productos
Si se elimina la factura, las líneas desaparecen con ella
Una línea pertenece a exactamente una factura
Ciclo de vida:
Figure 11:Ciclo de vida en una relación de composición: las partes mueren con el todo.
Agregación¶
La agregación es una relación débil de tipo “tiene-un” donde:
El contenedor agrupa o contiene objetos
Los objetos contenidos pueden existir independientemente
El ciclo de vida no está acoplado
Analogía: Departamento y Profesores¶
Un departamento universitario tiene profesores, pero:
Los profesores existían antes de unirse al departamento
Si el departamento se disuelve, los profesores siguen existiendo
Un profesor puede cambiar de departamento
Representación UML¶
La agregación se representa con un diamante vacío (◊) en el extremo del contenedor:
Figure 12:Agregación: el Departamento agrupa Profesores que existen independientemente.
El diamante blanco indica una relación de pertenencia más laxa.
Características de la Agregación¶
Ciclo de vida independiente: Las partes pueden existir antes y después del contenedor
Recepción de referencias: El contenedor recibe objetos ya creados (típicamente en constructor o setters)
Cardinalidad flexible: Una parte puede pertenecer a múltiples contenedores
Semántica débil: “Agrupa a” o “Contiene temporalmente”
Ejemplos de agregación:
Equipo◊─Jugador: Los jugadores pueden cambiar de equipoBiblioteca◊─Libro: Los libros existían antes y pueden moverse entre bibliotecasPlayList◊─Cancion: Las canciones pueden estar en múltiples playlists
Ejemplo Detallado: Equipo de Fútbol¶
Un equipo de fútbol agrupa jugadores:
¿Por qué es agregación?
Los jugadores existían antes de unirse al equipo (nacieron, crecieron, jugaron en otros equipos)
Los jugadores pueden cambiar de equipo (pases, transferencias)
Si el equipo se disuelve, los jugadores siguen existiendo (pueden retirarse o ir a otro equipo)
Un jugador puede incluso pertenecer a múltiples contextos (equipo + selección nacional)
Ciclo de vida:
Figure 13:Ciclo de vida en una relación de agregación: las partes sobreviven al contenedor.
Comparación: Composición vs Agregación¶
Table 2:Diferencias clave entre Composición y Agregación
| Aspecto | Composición (♦) | Agregación (◊) |
|---|---|---|
| Ciclo de vida | Acoplado (se crea y destruye junto) | Independiente (preexiste y sobrevive) |
| Creación | El todo crea las partes | Las partes se pasan al todo |
| Destrucción | Se destruyen con el todo | Sobreviven al todo |
| Exclusividad | Una parte pertenece a un solo todo | Una parte puede pertenecer a varios contenedores |
| Semántica | “No existe sin” | “Pertenece temporalmente a” |
| Fuerza | Relación fuerte | Relación débil |
¿Cuándo Usar Cada Una?¶
Usá Composición cuando:
Las partes no tienen sentido fuera del contexto del todo
El todo es responsable de crear las partes
La destrucción del todo implica la destrucción de las partes
Ejemplo:
Persona♦─Corazon,Casa♦─Cimientos
Usá Agregación cuando:
Las partes pueden existir independientemente
Las partes se crean fuera del contenedor y se le pasan
El contenedor es solo un “agrupador” o “coordinador”
Ejemplo:
Curso◊─Estudiante,Carpeta◊─Archivo
El Patrón Todo-Parte¶
Tanto la composición como la agregación son instancias del patrón estructural Todo-Parte, que modela la relación entre un objeto complejo (todo) y sus componentes (partes).
Beneficios del Patrón¶
Modularidad: El todo delega responsabilidades a las partes
Reusabilidad: Las partes pueden reutilizarse en diferentes contextos (especialmente en agregación)
Jerarquía conceptual: Modela naturalmente estructuras jerárquicas
Ejemplo Mixto: Sistema de Biblioteca¶
Un sistema de biblioteca puede combinar composición y agregación:
Interpretación:
Una
Bibliotecacrea susSecciones(Infantil, Referencia, etc.) → ComposiciónUna
BibliotecacontieneLibrosque fueron adquiridos → AgregaciónUn
Libroestá compuesto porPaginas→ ComposiciónUn
Libroestá asociado aAutores(que pueden escribir múltiples libros) → Agregación
Caso de Estudio: Sistema Universitario¶
Analicemos un sistema más complejo para practicar la identificación de relaciones.
Requerimiento:
“Una universidad tiene facultades. Cada facultad ofrece carreras. Los estudiantes se inscriben en una carrera y cursan materias. Los profesores dictan materias y pertenecen a un departamento dentro de una facultad.”
Paso 1: Identificar clases principales
Universidad
Facultad
Carrera
Estudiante
Materia
Profesor
Departamento
Paso 2: Analizar relaciones
| Relación | Tipo | Justificación |
|---|---|---|
| Universidad – Facultad | ♦ | Las facultades no existen sin la universidad |
| Facultad – Departamento | ♦ | Los departamentos son parte de la facultad |
| Facultad – Carrera | ♦ | Las carreras pertenecen a una facultad específica |
| Carrera – Materia | ♦ | Las materias son parte del plan de estudios |
| Estudiante – Carrera | Asoc | Un estudiante puede cambiarse de carrera |
| Estudiante – Materia | Asoc | Se inscribe/cursa/aprueba materias |
| Profesor – Departamento | ◊ | El profesor existe independientemente |
| Profesor – Materia | Asoc | El profesor “dicta” materias (no las posee) |
Paso 3: Diagrama resultante
Figure 14:Jerarquía de clases en el sistema universitario, mostrando las relaciones de composición y agregación.
Paso 4: Cardinalidades
Figure 15:Cardinalidades detalladas para cada una de las relaciones del sistema universitario.
Lecturas:
Una universidad tiene 1 o más facultades
Una facultad tiene 1 o más departamentos y 1 o más carreras
Una carrera tiene al menos 5 materias
Un departamento agrupa 1 o más profesores
Un profesor dicta 1 o más materias; una materia puede ser dictada por varios profesores
Un estudiante está inscripto en exactamente 1 carrera
Un estudiante cursa 0 o más materias; una materia puede tener 0 o más estudiantes inscriptos
Referencias Cruzadas y Asociaciones Bidireccionales¶
En algunos casos, dos objetos necesitan conocerse mutuamente. Esto se llama asociación bidireccional.
¿Cuándo Son Necesarias?¶
Ejemplo: Pedido y Cliente
El pedido necesita saber quién lo realizó (Cliente)
El cliente necesita consultar sus pedidos
Esto crea una navegación en ambas direcciones:
Figure 16:Asociación bidireccional entre Cliente y Pedido.
Problemas de las Asociaciones Bidireccionales¶
Complejidad: Hay que mantener la consistencia en ambas direcciones
Acoplamiento: Las dos clases dependen mutuamente
Riesgo de inconsistencia: Si actualizás una dirección y no la otra
Cuándo Son Aceptables¶
Las asociaciones bidireccionales son aceptables cuando:
La navegación en ambos sentidos es una necesidad del dominio
Podés garantizar la consistencia (típicamente mediante métodos que actualizan ambos lados)
El beneficio supera el costo en complejidad
Ejemplo: Implementación Correcta¶
Si decidís que necesitás bidireccionalidad entre Cliente y Pedido, tenés que mantener la consistencia:
Clase Cliente {
- pedidos: Lista<Pedido>
+ agregarPedido(pedido) {
pedidos.agregar(pedido)
pedido.establecerCliente(this) // Mantiene consistencia
}
+ removerPedido(pedido) {
pedidos.remover(pedido)
pedido.establecerCliente(null) // Mantiene consistencia
}
}
Clase Pedido {
- cliente: Cliente
// Método interno, no público
~ establecerCliente(nuevoCliente) {
this.cliente = nuevoCliente
}
}Patrón recomendado: Un solo lado de la relación (el “dueño”) maneja las modificaciones. El otro lado tiene métodos de acceso restringido.
Alternativa: Evitar la Bidireccionalidad¶
En muchos casos, podés evitar la bidireccionalidad usando un repositorio o servicio:
Clase RepositorioPedidos {
+ buscarPorCliente(cliente): Lista<Pedido> {
// Busca en la base de datos o colección
return pedidos.filtrar(p -> p.cliente == cliente)
}
}Así, Cliente no necesita conocer sus pedidos directamente; los consultás a través del repositorio cuando los necesitás.
Resumen¶
Encapsulamiento¶
Oculta el estado interno y expone solo una interfaz pública
Protege invariantes del objeto
Reduce acoplamiento entre clases
Facilita mantenimiento al permitir cambios internos sin afectar clientes
Asociación¶
Relación general de “conoce a” o “usa a”
Ciclo de vida independiente
No implica propiedad
Se representa con línea simple en UML
Composición (♦)¶
Relación fuerte “tiene-un”
El todo crea y destruye las partes
Las partes no existen fuera del todo
Diamante negro en UML
Agregación (◊)¶
Relación débil “contiene a”
Las partes preexisten y sobreviven al contenedor
El contenedor solo agrupa
Diamante blanco en UML
Cardinalidad¶
Especifica cuántas instancias participan en la relación
Notaciones:
1,0..1,*,1..*,n..mSe lee desde el otro extremo de la relación
Próximos Pasos¶
En este capítulo viste los conceptos fundamentales de encapsulamiento y relaciones entre objetos. Para implementar estos conceptos en Java, consultá:
Sintaxis de Clases y Objetos: Sintaxis de clases, atributos, constructores y métodos
Ejercicios¶
Identificación de Relaciones¶
Solution to Exercise 1
Respuesta: Agregación (◊)
Justificación:
Los productos preexisten al pedido — están en el catálogo antes de que alguien los pida
Si se cancela el pedido, los productos siguen existiendo en el catálogo
Un producto puede estar en múltiples pedidos simultáneamente
El pedido no “crea” los productos, solo los referencia
Diagrama:
Figure 17:Relación de agregación entre Pedido y Producto en el contexto de un catálogo.
Nota: El pedido contiene líneas de pedido (cantidad + producto), pero la relación con el producto en sí es de agregación. Las líneas de pedido serían composición del pedido.
Solution to Exercise 2
a) Computadora – Procesador: Composición (♦)
El procesador fue diseñado/elegido para esa computadora específica
Si destruís la computadora, el procesador pierde su contexto de uso
Generalmente un procesador no se “reutiliza” en otra computadora
Sin embargo, esto es debatible: si considerás que los procesadores pueden venderse como repuestos, sería agregación. Depende del contexto del sistema.
b) Playlist – Cancion: Agregación (◊)
Las canciones preexisten a la playlist
Una canción puede estar en múltiples playlists
Si elimino la playlist, las canciones siguen existiendo
c) Documento – Parrafo: Composición (♦)
Los párrafos se crean dentro del documento
Un párrafo no tiene sentido fuera de su documento
Si elimino el documento, los párrafos desaparecen
d) Proyecto – Desarrollador: Agregación (◊)
Los desarrolladores existen antes de unirse al proyecto
Un desarrollador puede trabajar en múltiples proyectos
Si termina el proyecto, los desarrolladores siguen existiendo
Cardinalidad y UML¶
Solution to Exercise 3
Diagrama:
Figure 18:Asociación con cardinalidad específica entre Estudiante y Curso.
Lectura:
Un estudiante está inscripto en 0 o más cursos (
*)Un curso tiene entre 5 y 40 estudiantes (
5..40)
Alternativa con clase de asociación (si necesitamos guardar información de la inscripción):
Figure 19:Clase de asociación ‘Inscripción’ para capturar datos adicionales de la relación entre Estudiante y Curso.
Solution to Exercise 4
Diseño de la clase:
Clase Rectangulo {
// Atributos privados
- ancho: double
- alto: double
// Constructor que valida
+ Rectangulo(ancho, alto) {
validarDimension(ancho, "ancho")
validarDimension(alto, "alto")
this.ancho = ancho
this.alto = alto
}
// Métodos de consulta (getters válidos en este caso)
+ obtenerAncho(): double { return ancho }
+ obtenerAlto(): double { return alto }
// Métodos de modificación con validación
+ cambiarAncho(nuevoAncho) {
validarDimension(nuevoAncho, "ancho")
this.ancho = nuevoAncho
}
+ cambiarAlto(nuevoAlto) {
validarDimension(nuevoAlto, "alto")
this.alto = nuevoAlto
}
// Métodos de comportamiento
+ calcularArea(): double {
return ancho * alto
}
+ calcularPerimetro(): double {
return 2 * (ancho + alto)
}
// Método privado de validación
- validarDimension(valor, nombre) {
if (valor <= 0) {
lanzar error "El " + nombre + " debe ser mayor a 0"
}
}
}Garantías:
Los atributos son privados → no se pueden modificar directamente
El constructor valida → no se puede crear un rectángulo inválido
Los métodos de modificación validan → no se puede violar la invariante después
La lógica de validación está centralizada → fácil de mantener
Solution to Exercise 5
Análisis:
| Caso de uso | Dirección necesaria |
|---|---|
| Dado un libro, obtener su editorial | Libro → Editorial |
| Dada una editorial, obtener sus libros | Editorial → Libro |
Parece que necesitamos bidireccionalidad, pero hay alternativas.
Opción 1: Bidireccional simple
Libro {
- editorial: Editorial
+ obtenerEditorial(): Editorial
}
Editorial {
- libros: Lista<Libro>
+ obtenerLibros(): Lista<Libro>
}Problema: Hay que mantener consistencia en ambos lados.
Opción 2: Unidireccional + Repositorio (recomendada)
Libro {
- editorial: Editorial
+ obtenerEditorial(): Editorial
}
Editorial {
// No conoce directamente sus libros
}
RepositorioLibros {
+ buscarPorEditorial(editorial): Lista<Libro>
}Ventajas:
Libro→Editoriales la relación natural (el libro sabe quién lo publicó)La consulta inversa se hace a través del repositorio
No hay riesgo de inconsistencia
El modelo es más simple
Recomendación: Opción 2, especialmente si usás una base de datos donde las consultas inversas son eficientes.
Ejercicio Integrador¶
Solution to Exercise 6
1. Clases identificadas:
Hospital
Piso
Habitacion
Cama
Paciente
Medico
Especialidad
Enfermera
2. Análisis de relaciones:
| Relación | Tipo | Justificación |
|---|---|---|
| Hospital – Piso | ♦ | Los pisos son parte estructural del hospital |
| Piso – Habitacion | ♦ | Las habitaciones son parte del piso |
| Habitacion – Cama | ♦ | Las camas son parte de la habitación |
| Cama – Paciente | Asoc | El paciente existe independientemente |
| Medico – Paciente | Asoc | Relación de “atiende”, no de posesión |
| Medico – Especialidad | ◊ | Las especialidades preexisten |
| Piso – Enfermera | ◊ | Las enfermeras pueden cambiar de piso |
3. Diagrama con cardinalidades:
Figure 20:Modelo de clases completo para el sistema hospitalario, integrando diversos tipos de relaciones y cardinalidades.
4. Justificaciones detalladas:
Hospital ♦── Piso:
Un piso no tiene sentido fuera del hospital
El hospital define cuántos pisos tiene desde su construcción
Piso ♦── Habitacion:
Las habitaciones son parte del piso
Si “destruís” el piso (remodelación total), las habitaciones desaparecen
Habitacion ♦── Cama:
Las camas están fijas en la habitación
Cardinalidad 1..4 porque puede ser simple (1) o compartida (2-4)
Cama ── Paciente:
Asociación simple: el paciente “ocupa” la cama temporalmente
Cardinalidad 0..1: una cama puede estar vacía o tener un paciente
Piso ◊── Enfermera:
Las enfermeras existen independientemente del piso
Pueden ser reasignadas a otros pisos
Cardinalidad 1..* en piso: al menos una enfermera por piso
Medico ── Paciente:
Relación de “atiende”, no posesión
Un médico atiende varios pacientes
Un paciente puede ser atendido por varios médicos
Medico ◊── Especialidad:
Las especialidades (Cardiología, Pediatría) preexisten
Un médico puede tener varias especialidades
Las especialidades no desaparecen si el médico deja el hospital
Próximo paso¶
Para seguir, conviene pasar a el material siguiente, donde el recorrido continúa sobre esta base.