Comprender la diferencia entre abstracción y encapsulamiento Dominar los modificadores de acceso en Java Entender el rol de la composición en el diseño OO Aplicar estos conceptos en diseños prácticos
| Aspecto | Abstracción | Encapsulamiento |
|---|---|---|
| Enfoque | QUÉ hace algo | CÓMO proteger datos |
| Propósito | Manejar complejidad | Proteger integridad |
| Mecanismo | Métodos públicos simples | Modificadores de acceso |
| Resultado | Simplicidad | Seguridad |
// Ejemplo de abstracción
public class ControlRemoto {
private int canal;
private int volumen;
private boolean encendido;
// Métodos públicos simples que ocultan la complejidad
public void encender() {
// Oculta toda la complejidad de encender el TV
inicializarSistema();
cargarConfiguracion();
encendido = true;
}
public void cambiarCanal(int nuevoCanal) {
if (encendido && nuevoCanal > 0) {
this.canal = nuevoCanal;
sintonizarSenal();
ajustarAntena();
}
}
// Métodos privados que contienen la complejidad
private void inicializarSistema() { /* ... */ }
private void cargarConfiguracion() { /* ... */ }
private void sintonizarSenal() { /* ... */ }
private void ajustarAntena() { /* ... */ }
}
public class CuentaBancaria {
private double saldo; // Dato protegido
private String pin; // Dato protegido
public CuentaBancaria(String pin, double saldoInicial) {
if (saldoInicial < 0) {
throw new IllegalArgumentException("Saldo inicial no puede ser negativo");
}
this.pin = pin;
this.saldo = saldoInicial;
}
public boolean retirar(double monto, String pinIngresado) {
if (!validarPin(pinIngresado)) return false;
if (monto <= saldo && monto > 0) {
saldo -= monto;
return true;
}
return false;
}
private boolean validarPin(String pinIngresado) {
return this.pin.equals(pinIngresado);
}
public double consultarSaldo(String pinIngresado) {
if (validarPin(pinIngresado)) {
return saldo;
}
throw new SecurityException("PIN inválido");
}
}
| Modificador | Clase | Paquete | Subclase (mismo paquete) | Subclase (otro paquete) | Mundo |
|---|---|---|---|---|---|
private | ✓ | ✗ | ✗ | ✗ | ✗ |
default | ✓ | ✓ | ✓ | ✗ | ✗ |
protected | ✓ | ✓ | ✓ | ✓ | ✗ |
public | ✓ | ✓ | ✓ | ✓ | ✓ |
Notas:
default: Es el modificador que se aplica cuando no se especifica ningunoprotected: Da acceso a subclases sin importar el paquete, y a todas las clases en el mismo paquetedefaultLa composición es útil para modularidad y reusabilidad, y facilita la abstracción al construir objetos complejos:
// Ejemplo de composición
public class Automovil {
// Composición de partes
private Motor motor;
private Transmision transmision;
private SistemaElectrico sistemaElectrico;
public Automovil() {
this.motor = new Motor();
this.transmision = new Transmision();
this.sistemaElectrico = new SistemaElectrico();
}
// Métodos públicos simples que usan la composición
public void arrancar() {
motor.encender();
transmision.ponerEnNeutral();
sistemaElectrico.activar();
}
public void acelerar() {
if (motor.estaEncendido()) {
motor.aumentarRPM();
transmision.ajustarVelocidad();
}
}
}
Objetivo: Crear un sistema que demuestre abstracción y encapsulamiento
public class ReproductorMusica {
private int volumenActual;
private boolean encendido;
private String cancionActual;
// Composición
private Amplificador amplificador;
private Parlantes parlantes;
public ReproductorMusica() {
this.amplificador = new Amplificador();
this.parlantes = new Parlantes();
this.volumenActual = 0;
this.encendido = false;
}
public void encender() {
encendido = true;
amplificador.inicializar();
parlantes.activar();
}
public void reproducir(String cancion) {
if (encendido) {
this.cancionActual = cancion;
amplificador.procesarAudio(cancion);
parlantes.emitirSonido();
}
}
public void ajustarVolumen(int nivel) {
if (nivel >= 0 && nivel <= 100) {
this.volumenActual = nivel;
amplificador.ajustarGanancia(nivel);
parlantes.ajustarVolumen(nivel);
}
}
}
Objetivo: Implementar un sistema seguro usando los conceptos aprendidos
public class CuentaBancaria {
// Encapsulamiento de datos
private double saldo;
private List<String> historialTransacciones;
// Composición
private SistemaSeguridad seguridad;
private RegistradorTransacciones registrador;
public CuentaBancaria(double saldoInicial) {
this.saldo = saldoInicial;
this.historialTransacciones = new ArrayList<>();
this.seguridad = new SistemaSeguridad();
this.registrador = new RegistradorTransacciones();
}
public boolean realizarTransaccion(double monto, String pin) {
if (!seguridad.validarPin(pin)) {
return false;
}
if (monto <= saldo && monto > 0) {
saldo -= monto;
registrador.registrarMovimiento(monto);
return true;
}
return false;
}
}
Objetivo: Crear un sistema que demuestre los tres conceptos principales:
public class Pedido {
// Encapsulamiento
private int numeroOrden;
private List<Plato> platos;
private double total;
private String estado;
// Composición
private Cocina cocina;
private Facturacion facturacion;
public Pedido(int numeroOrden) {
this.numeroOrden = numeroOrden;
this.platos = new ArrayList<>();
this.estado = "NUEVO";
this.cocina = new Cocina();
this.facturacion = new Facturacion();
}
public void agregarPlato(Plato plato) {
if (cocina.verificarDisponibilidad(plato)) {
platos.add(plato);
total += plato.getPrecio();
cocina.prepararPlato(plato);
}
}
public double generarCuenta() {
return facturacion.calcularTotal(platos);
}
}
public class Plato {
private String nombre;
private double precio;
private List<Ingrediente> ingredientes;
// Composición
private RecetaPreparacion receta;
public Plato(String nombre, double precio) {
this.nombre = nombre;
this.precio = precio;
this.ingredientes = new ArrayList<>();
this.receta = new RecetaPreparacion();
}
public void agregarIngrediente(Ingrediente ingrediente) {
ingredientes.add(ingrediente);
}
public double getPrecio() {
return precio;
}
}
public class GestorPedidos {
private List<Pedido> pedidosPendientes;
private Cocina cocina;
public void tomarPedido(Pedido pedido) {
pedidosPendientes.add(pedido);
cocina.notificarNuevoPedido(pedido);
}
public List<Pedido> obtenerPedidosPendientes() {
return new ArrayList<>(pedidosPendientes);
}
}
public class Inventario {
private Map<String, Integer> stockIngredientes;
public boolean verificarStock(String ingrediente, int cantidad) {
return stockIngredientes.getOrDefault(ingrediente, 0) >= cantidad;
}
public void actualizarStock(String ingrediente, int cantidad) {
stockIngredientes.put(ingrediente,
stockIngredientes.getOrDefault(ingrediente, 0) - cantidad);
}
}