Nivel 2 · 20 min
Composición vs Herencia
''Favorecé composición sobre herencia'' — principio de Effective Java. La composición (tener una referencia a otro objeto) es más flexible que la herencia (ser un subtipo de otro objeto). No es que la herencia sea mala — es que la composición resuelve muchos casos mejor y con menos acoplamiento.
Los problemas de la herencia
La herencia es inflexible — la relación se define en compile-time y no puede cambiar en runtime. El Fragile Base Class problem: cambios en la superclase pueden romper subclases de formas inesperadas. La herencia expone los internos de la superclase a las subclases — viola encapsulación. La herencia de implementación crea acoplamiento estrecho entre superclase y subclases.
Composición y sus ventajas
Con composición, un objeto contiene una referencia a otro y delega operaciones en él. Las ventajas: podés cambiar el comportamiento en runtime (estrategia inyectada), la clase que compone no conoce los internos de la clase compuesta (encapsulación respetada), podés combinar múltiples comportamientos (múltiples campos de estrategia), y los cambios en el objeto compuesto no rompen al que compone.
Decorator como composición
El patrón Decorator es composición en acción: envolvés un objeto con otro que implementa la misma interfaz y delega, agregando comportamiento. Podés apilar Decorators para combinar comportamientos. Java I/O lo usa extensivamente: FileInputStream → BufferedInputStream → GZIPInputStream. Cada capa agrega funcionalidad sin subclasificar.
Code example
// Composicion: Logger flexible
class OrderService {
private final OrderRepository repo;
private final EventPublisher events;
private final MetricsCollector metrics; // compuesto, no heredado
void createOrder(Order o) {
repo.save(o);
events.publish(new OrderCreated(o));
metrics.increment("orders.created");
}
}