Patrones de Diseño: Patrones Creacionales - Singleton, Factory, Builder, Prototype y Abstract Factory
Más artículos sobre Patrones de Diseño:
- Fundamentos de Patrones de Diseño (GoF)
- Catálogo de Patrones de Diseño
- Descripción General de Patrones de Diseño
Este artículo es una guía completa de los Patrones de Diseño Creacionales, incluyendo Singleton, Factory, Builder, Prototype y Abstract Factory con ejemplos prácticos.
En Pocas Palabras
Los Patrones Creacionales abstraen la creación de objetos. Singleton garantiza una única instancia, Factory encapsula la lógica de creación, Builder permite construir objetos paso a paso, Prototype clona objetos y Abstract Factory crea familias de objetos relacionados.
Descripción Técnica Compacta
Los Patrones de Diseño Creacionales son patrones que controlan el proceso de instanciación de objetos y hacen este proceso más flexible.
Patrones Creacionales importantes:
Patrón Singleton
- Propósito: Garantizar una única instancia
- Aplicación: Loggers, configuración, thread pools
- Implementación: Constructor privado, instancia estática
- Thread-Safety: Sincronización o inicialización eager
Patrón Factory Method
- Propósito: Delegar la creación de objetos a subclases
- Aplicación: Frameworks, sistemas de plugins
- Implementación: Método factory abstracto
- Ventaja: Bajo acoplamiento, extensibilidad
Patrón Abstract Factory
- Propósito: Crear familias de objetos relacionados
- Aplicación: Toolkits de UI, drivers de base de datos
- Implementación: Interfaz Factory con factories concretas
- Ventaja: Familias de objetos consistentes
Patrón Builder
- Propósito: Construir objetos complejos paso a paso
- Aplicación: Objetos de configuración, DSLs
- Implementación: Fluent Interface, clase Builder separada
- Ventaja: Legibilidad, flexibilidad
Patrón Prototype
- Propósito: Crear objetos mediante clonación
- Aplicación: Creación optimizada para rendimiento
- Implementación: Interfaz Cloneable, método clone()
- Ventaja: Ahorro cuando la creación es costosa
Puntos Clave Relevantes para Exámenes
- Patrones Creacionales: Patrones para instanciación flexible de objetos
- Singleton: Una única instancia, puntos de acceso global
- Factory Method: Creación de objetos delegada a subclases
- Abstract Factory: Crear familias de objetos
- Builder: Construcción paso a paso de objetos complejos
- Prototype: Crear objetos mediante clonación
- Relevancia IHK: Importante para arquitectura de software flexible
Componentes Clave
- Singleton: Instancia global con acceso controlado
- Factory Method: Creación de objetos abstraída
- Abstract Factory: Interfaz para familias de objetos
- Builder: Fluent Interface para construcción compleja
- Prototype: Creación de objetos basada en clonación
- Dependency Injection: Inversión de control
- Factory Configuration: Creación basada en configuración
- Object Pool: Reutilización de objetos
Ejemplos Prácticos
1. Patrón Singleton
// Inicialización Eager (Thread-Safe)
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {
// Constructor privado evita instanciación
}
public static EagerSingleton getInstance() {
return INSTANCE;
}
public void doSomething() {
System.out.println("Eager Singleton funcionando");
}
}
// Inicialización Lazy con Double-Checked Locking
public class LazySingleton {
private static volatile LazySingleton instance;
private LazySingleton() {
// Constructor privado
}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
public void performAction() {
System.out.println("Lazy Singleton en acción");
}
}
// Singleton con Enum (Thread-Safe, Serialization-Safe)
public enum EnumSingleton {
INSTANCE;
public void doWork() {
System.out.println("Enum Singleton funcionando");
}
}
// Logger como Singleton
public class Logger {
private static volatile Logger instance;
private final List<String> logs = new ArrayList<>();
private Logger() {}
public static Logger getInstance() {
if (instance == null) {
synchronized (Logger.class) {
if (instance == null) {
instance = new Logger();
}
}
}
return instance;
}
public void log(String message) {
String timestamp = new Date().toString();
String logEntry = "[" + timestamp + "] " + message;
logs.add(logEntry);
System.out.println(logEntry);
}
public List<String> getLogs() {
return new ArrayList<>(logs);
}
public void clearLogs() {
logs.clear();
}
}
// Demo de Singleton
public class SingletonDemo {
public static void main(String[] args) {
System.out.println("=== Demo del Patrón Singleton ===");
// Eager Singleton
EagerSingleton eager1 = EagerSingleton.getInstance();
EagerSingleton eager2 = EagerSingleton.getInstance();
System.out.println("Eager Singleton - Misma instancia: " + (eager1 == eager2));
eager1.doSomething();
// Lazy Singleton
LazySingleton lazy1 = LazySingleton.getInstance();
LazySingleton lazy2 = LazySingleton.getInstance();
System.out.println("Lazy Singleton - Misma instancia: " + (lazy1 == lazy2));
lazy2.performAction();
// Enum Singleton
EnumSingleton enum1 = EnumSingleton.INSTANCE;
EnumSingleton enum2 = EnumSingleton.INSTANCE;
System.out.println("Enum Singleton - Misma instancia: " + (enum1 == enum2));
enum1.doWork();
// Logger Singleton
Logger logger1 = Logger.getInstance();
Logger logger2 = Logger.getInstance();
System.out.println("Logger Singleton - Misma instancia: " + (logger1 == logger2));
logger1.log("Aplicación iniciada");
logger2.log("Usuario autenticado");
System.out.println("Logs: " + logger1.getLogs());
}
}
2. Patrón Factory Method
// Clase abstracta del producto
abstract class Vehiculo {
protected String marca;
protected String modelo;
public Vehiculo(String marca, String modelo) {
this.marca = marca;
this.modelo = modelo;
}
public abstract void iniciar();
public abstract void frenar();
@Override
public String toString() {
return marca + " " + modelo;
}
}
// Productos concretos
class Auto extends Vehiculo {
public Auto(String marca, String modelo) {
super(marca, modelo);
}
@Override
public void iniciar() {
System.out.println("Auto " + this + " iniciado");
}
@Override
public void frenar() {
System.out.println("Auto " + this + " frenado");
}
}
class Motocicleta extends Vehiculo {
public Motocicleta(String marca, String modelo) {
super(marca, modelo);
}
@Override
public void iniciar() {
System.out.println("Motocicleta " + this + " iniciada");
}
@Override
public void frenar() {
System.out.println("Motocicleta " + this + " frenada");
}
}
// Clase factory abstracta
abstract class FabricaVehiculo {
// Factory Method
public abstract Vehiculo crearVehiculo(String marca, String modelo);
// Template Method
public void producirYProbar(String marca, String modelo) {
Vehiculo vehiculo = crearVehiculo(marca, modelo);
System.out.println("Producido: " + vehiculo);
// Prueba de calidad
vehiculo.iniciar();
vehiculo.frenar();
System.out.println("Prueba superada");
}
}
// Factories concretas
class FabricaAuto extends FabricaVehiculo {
@Override
public Vehiculo crearVehiculo(String marca, String modelo) {
return new Auto(marca, modelo);
}
}
class FabricaMotocicleta extends FabricaVehiculo {
@Override
public Vehiculo crearVehiculo(String marca, String modelo) {
return new Motocicleta(marca, modelo);
}
}
// Factory con parámetro
class FabricaVehiculoSimple {
public static Vehiculo crearVehiculo(String tipo, String marca, String modelo) {
switch (tipo.toLowerCase()) {
case "auto":
return new Auto(marca, modelo);
case "motocicleta":
return new Motocicleta(marca, modelo);
default:
throw new IllegalArgumentException("Tipo de vehículo desconocido: " + tipo);
}
}
}
// Demo Factory Method
public class FactoryMethodDemo {
public static void main(String[] args) {
System.out.println("=== Demo del Patrón Factory Method ===");
// Factory Method Pattern
FabricaVehiculo fabricaAuto = new FabricaAuto();
FabricaVehiculo fabricaMotocicleta = new FabricaMotocicleta();
System.out.println("--- Producción de Autos ---");
fabricaAuto.producirYProbar("VW", "Golf");
System.out.println("\n--- Producción de Motocicletas ---");
fabricaMotocicleta.producirYProbar("BMW", "R1200");
// Static Factory
System.out.println("\n--- Static Factory ---");
Vehiculo vwGolf = FabricaVehiculoSimple.crearVehiculo("auto", "VW", "Golf");
Vehiculo bmwR1200 = FabricaVehiculoSimple.crearVehiculo("motocicleta", "BMW", "R1200");
vwGolf.iniciar();
bmwR1200.iniciar();
// Factory con configuración
System.out.println("\n--- Factory con Configuración ---");
ConfiguradorVehiculo configurador = new ConfiguradorVehiculo();
Vehiculo auto1 = configurador.crearVehiculo("auto", "Mercedes", "Clase C");
Vehiculo motocicleta1 = configurador.crearVehiculo("motocicleta", "Harley", "Sportster");
auto1.iniciar();
motocicleta1.iniciar();
}
}
// Factory con configuración
class ConfiguradorVehiculo {
private Map<String, FabricaVehiculo> fabricas = new HashMap<>();
public ConfiguradorVehiculo() {
fabricas.put("auto", new FabricaAuto());
fabricas.put("motocicleta", new FabricaMotocicleta());
}
public Vehiculo crearVehiculo(String tipo, String marca, String modelo) {
FabricaVehiculo fabrica = fabricas.get(tipo.toLowerCase());
if (fabrica == null) {
throw new IllegalArgumentException("Tipo desconocido: " + tipo);
}
return fabrica.crearVehiculo(marca, modelo);
}
public void registrarFabrica(String tipo, FabricaVehiculo fabrica) {
fabricas.put(tipo.toLowerCase(), fabrica);
}
}
3. Patrón Abstract Factory
// Productos abstractos para tema UI
interface Button {
void render();
void onClick(Runnable action);
}
interface TextField {
void render();
void setText(String text);
String getText();
}
interface Checkbox {
void render();
void setChecked(boolean checked);
boolean isChecked();
}
// Productos concretos - Tema Windows
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("[Windows Button renderizado]");
}
@Override
public void onClick(Runnable action) {
System.out.println("Windows Button clickeado");
action.run();
}
}
class WindowsTextField implements TextField {
private String text = "";
@Override
public void render() {
System.out.println("[Windows TextField: '" + text + "']");
}
@Override
public void setText(String text) {
this.text = text;
}
@Override
public String getText() {
return text;
}
}
class WindowsCheckbox implements Checkbox {
private boolean checked = false;
@Override
public void render() {
System.out.println("[Windows Checkbox: " + (checked ? "X" : " ") + "]");
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
@Override
public boolean isChecked() {
return checked;
}
}
// Productos concretos - Tema macOS
class MacButton implements Button {
@Override
public void render() {
System.out.println("[macOS Button renderizado]");
}
@Override
public void onClick(Runnable action) {
System.out.println("macOS Button clickeado");
action.run();
}
}
class MacTextField implements TextField {
private String text = "";
@Override
public void render() {
System.out.println("[macOS TextField: '" + text + "']");
}
@Override
public void setText(String text) {
this.text = text;
}
@Override
public String getText() {
return text;
}
}
class MacCheckbox implements Checkbox {
private boolean checked = false;
@Override
public void render() {
System.out.println("[macOS Checkbox: " + (checked ? "✓" : " ") + "]");
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
@Override
public boolean isChecked() {
return checked;
}
}
// Factory abstracta
interface GUIFactory {
Button createButton();
TextField createTextField();
Checkbox createCheckbox();
}
// Factories concretas
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
@Override
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// Código cliente
class Aplicacion {
private Button button;
private TextField textField;
private Checkbox checkbox;
public Aplicacion(GUIFactory factory) {
button = factory.createButton();
textField = factory.createTextField();
checkbox = factory.createCheckbox();
}
public void crearUI() {
System.out.println("=== UI siendo creada ===");
button.render();
textField.render();
checkbox.render();
// Añadir funcionalidad
button.onClick(() -> {
String text = textField.getText();
System.out.println("Button clickeado con texto: " + text);
checkbox.setChecked(!checkbox.isChecked());
checkbox.render();
});
textField.setText("Texto de ejemplo");
textField.render();
}
}
// Demo de Abstract Factory
public class AbstractFactoryDemo {
public static void main(String[] args) {
System.out.println("=== Abstract Factory Pattern Demo ===");
// Aplicación Windows
System.out.println("\n--- Aplicación Windows ---");
GUIFactory windowsFactory = new WindowsFactory();
Aplicacion windowsApp = new Aplicacion(windowsFactory);
windowsApp.crearUI();
// Aplicación macOS
System.out.println("\n--- Aplicación macOS ---");
GUIFactory macFactory = new MacFactory();
Aplicacion macApp = new Aplicacion(macFactory);
macApp.crearUI();
// Factory basada en sistema operativo
System.out.println("\n--- Factory dinámica ---");
String os = System.getProperty("os.name").toLowerCase();
GUIFactory factory;
if (os.contains("mac")) {
factory = new MacFactory();
} else {
factory = new WindowsFactory();
}
Aplicacion appDinamica = new Aplicacion(factory);
appDinamica.crearUI();
}
}
4. Patrón Builder
// Producto complejo
class Computer {
private final String cpu;
private final String gpu;
private final int ram;
private final int storage;
private final boolean hasWifi;
private final boolean hasBluetooth;
private final String operatingSystem;
// Constructor privado
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.gpu = builder.gpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.hasWifi = builder.hasWifi;
this.hasBluetooth = builder.hasBluetooth;
this.operatingSystem = builder.operatingSystem;
}
// Getters
public String getCpu() { return cpu; }
public String getGpu() { return gpu; }
public int getRam() { return ram; }
public int getStorage() { return storage; }
public boolean hasWifi() { return hasWifi; }
public boolean hasBluetooth() { return hasBluetooth; }
public String getOperatingSystem() { return operatingSystem; }
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", ram=" + ram + "GB" +
", storage=" + storage + "GB" +
", hasWifi=" + hasWifi +
", hasBluetooth=" + hasBluetooth +
", operatingSystem='" + operatingSystem + '\'' +
'}';
}
// Clase Builder
public static class Builder {
// Parámetros requeridos
private final String cpu;
private final String gpu;
// Parámetros opcionales con valores por defecto
private int ram = 8;
private int storage = 256;
private boolean hasWifi = true;
private boolean hasBluetooth = false;
private String operatingSystem = "Windows";
// Constructor para parámetros requeridos
public Builder(String cpu, String gpu) {
this.cpu = cpu;
this.gpu = gpu;
}
// Interfaz fluida para parámetros opcionales
public Builder ram(int ram) {
this.ram = ram;
return this;
}
public Builder storage(int storage) {
this.storage = storage;
return this;
}
public Builder wifi(boolean hasWifi) {
this.hasWifi = hasWifi;
return this;
}
public Builder bluetooth(boolean hasBluetooth) {
this.hasBluetooth = hasBluetooth;
return this;
}
public Builder operatingSystem(String operatingSystem) {
this.operatingSystem = operatingSystem;
return this;
}
// Método build
public Computer build() {
// Validación
if (ram < 4) {
throw new IllegalArgumentException("RAM debe ser al menos 4GB");
}
if (storage < 128) {
throw new IllegalArgumentException("Storage debe ser al menos 128GB");
}
return new Computer(this);
}
}
}
// Builder para objetos de configuración
class Configuracion {
private final Map<String, String> propiedades;
private final List<String> modulosActivos;
private final String conexionBaseDatos;
private final int timeout;
private Configuracion(Builder builder) {
this.propiedades = new HashMap<>(builder.propiedades);
this.modulosActivos = new ArrayList<>(builder.modulosActivos);
this.conexionBaseDatos = builder.conexionBaseDatos;
this.timeout = builder.timeout;
}
public static class Builder {
private Map<String, String> propiedades = new HashMap<>();
private List<String> modulosActivos = new ArrayList<>();
private String conexionBaseDatos = "localhost:5432";
private int timeout = 30;
public Builder propiedad(String clave, String valor) {
propiedades.put(clave, valor);
return this;
}
public Builder modulo(String modulo) {
modulosActivos.add(modulo);
return this;
}
public Builder conexionBaseDatos(String conexion) {
this.conexionBaseDatos = conexion;
return this;
}
public Builder timeout(int segundos) {
this.timeout = segundos;
return this;
}
public Configuracion build() {
return new Configuracion(this);
}
}
// Getters y toString
public Map<String, String> getPropiedades() { return new HashMap<>(propiedades); }
public List<String> getModulosActivos() { return new ArrayList<>(modulosActivos); }
public String getConexionBaseDatos() { return conexionBaseDatos; }
public int getTimeout() { return timeout; }
@Override
public String toString() {
return "Configuracion{" +
"propiedades=" + propiedades +
", modulosActivos=" + modulosActivos +
", conexionBaseDatos='" + conexionBaseDatos + '\'' +
", timeout=" + timeout +
'}';
}
}
// Demo de Builder Pattern
public class BuilderDemo {
public static void main(String[] args) {
System.out.println("=== Builder Pattern Demo ===");
// PC gaming simple con Builder
Computer gamingPC = new Computer.Builder("Intel i9", "NVIDIA RTX 3080")
.ram(32)
.storage(1000)
.wifi(true)
.bluetooth(true)
.operatingSystem("Windows 11")
.build();
System.out.println("Gaming PC: " + gamingPC);
// PC de oficina minimal
Computer officePC = new Computer.Builder("Intel i5", "Intel HD Graphics")
.build();
System.out.println("Office PC: " + officePC);
// Configuración con Builder
Configuracion config = new Configuracion.Builder()
.propiedad("app.name", "MyApp")
.propiedad("app.version", "1.0.0")
.modulo("authentication")
.modulo("logging")
.modulo("database")
.conexionBaseDatos("prod.db.server.com:5432")
.timeout(60)
.build();
System.out.println("\nConfiguración: " + config);
// Builder anidado
System.out.println("\n--- Builder Anidado ---");
Computer server = new Computer.Builder("AMD EPYC", "AMD Radeon VII")
.ram(128)
.storage(4000)
.wifi(false)
.operatingSystem("Ubuntu Server")
.build();
System.out.println("Server: " + server);
// Builder con validación
try {
Computer invalidPC = new Computer.Builder("Intel i3", "Intel HD")
.ram(2) // Inválido
.build();
} catch (IllegalArgumentException e) {
System.out.println("Error de validación: " + e.getMessage());
}
}
}
5. Patrón Prototype
// Interfaz Prototype
interface Prototype<T> {
T clone();
}
// Prototipos concretos
class Dokument implements Prototype<Dokument> {
private String titel;
private String inhalt;
private List<String> tags;
private Date erstellDatum;
public Dokument(String titel, String inhalt) {
this.titel = titel;
this.inhalt = inhalt;
this.tags = new ArrayList<>();
this.erstellDatum = new Date();
}
// Copy Constructor
private Dokument(Dokument original) {
this.titel = original.titel;
this.inhalt = original.inhalt;
this.tags = new ArrayList<>(original.tags);
this.erstellDatum = new Date(original.erstellDatum.getTime());
}
@Override
public Dokument clone() {
return new Dokument(this);
}
// Getters y setters
public String getTitel() { return titel; }
public void setTitel(String titel) { this.titel = titel; }
public String getInhalt() { return inhalt; }
public void setInhalt(String inhalt) { this.inhalt = inhalt; }
public void addTag(String tag) { tags.add(tag); }
public List<String> getTags() { return new ArrayList<>(tags); }
@Override
public String toString() {
return "Dokument{" +
"titel='" + titel + '\'' +
", inhalt='" + inhalt + '\'' +
", tags=" + tags +
", erstellDatum=" + erstellDatum +
'}';
}
}
// Objeto gráfico como prototipo
class GrafikObjekt implements Prototype<GrafikObjekt> {
private String typ;
private int x, y;
private int breite, hoehe;
private String farbe;
private List<GrafikObjekt> kinder;
public GrafikObjekt(String typ, int x, int y, int breite, int hoehe, String farbe) {
this.typ = typ;
this.x = x;
this.y = y;
this.breite = breite;
this.hoehe = hoehe;
this.farbe = farbe;
this.kinder = new ArrayList<>();
}
// Deep clone con copy constructor
private GrafikObjekt(GrafikObjekt original) {
this.typ = original.typ;
this.x = original.x;
this.y = original.y;
this.breite = original.breite;
this.hoehe = original.hoehe;
this.farbe = original.farbe;
this.kinder = new ArrayList<>();
// Deep clone para los hijos
for (GrafikObjekt kind : original.kinder) {
this.kinder.add(kind.clone());
}
}
@Override
public GrafikObjekt clone() {
return new GrafikObjekt(this);
}
public void addKind(GrafikObjekt kind) {
kinder.add(kind);
}
public void verschieben(int deltaX, int deltaY) {
this.x += deltaX;
this.y += deltaY;
// Los hijos también se desplazan
for (GrafikObjekt kind : kinder) {
kind.verschieben(deltaX, deltaY);
}
}
@Override
public String toString() {
return "GrafikObjekt{" +
"typ='" + typ + '\'' +
", x=" + x + ", y=" + y +
", groesse=" + breite + "x" + hoehe +
", farbe='" + farbe + '\'' +
", kinder=" + kinder.size() +
'}';
}
}
// Registro de prototipos
class PrototypeRegistry {
private Map<String, Prototype<?>> prototypen = new HashMap<>();
public void registrierePrototyp(String key, Prototype<?> prototyp) {
prototypen.put(key, prototyp);
}
@SuppressWarnings("unchecked")
public <T extends Prototype<T>> T klonePrototyp(String key) {
Prototype<?> prototyp = prototypen.get(key);
if (prototyp == null) {
throw new IllegalArgumentException("Prototyp nicht gefunden: " + key);
}
return (T) prototyp.clone();
}
public Collection<String> getVerfuegbarePrototypen() {
return prototypen.keySet();
}
}
// Gestor de prototipos para optimización de rendimiento
class PerformancePrototypManager {
private Map<Class<?>, Prototype<?>> cache = new HashMap<>();
@SuppressWarnings("unchecked")
public <T extends Prototype<T>> T getOptimiertesClone(Class<T> klasse, T prototyp) {
if (!cache.containsKey(klasse)) {
cache.put(klasse, prototyp);
}
T cached = (T) cache.get(klasse);
return cached.clone();
}
public void clearCache() {
cache.clear();
}
public int getCacheSize() {
return cache.size();
}
}
// Demo del patrón Prototype
public class PrototypeDemo {
public static void main(String[] args) {
System.out.println("=== Prototype Pattern Demo ===");
// Clonación simple
System.out.println("\n--- Clonación simple ---");
Dokument original = new Dokument("Bericht", "Dies ist ein Testbericht");
original.addTag("wichtig");
original.addTag("intern");
System.out.println("Original: " + original);
Dokument kopie = original.clone();
kopie.setTitel("Bericht - Kopie");
kopie.addTag("kopie");
System.out.println("Kopie: " + kopie);
System.out.println("Original nach Kopie: " + original);
// Deep clone con objetos complejos
System.out.println("\n--- Deep clone ---");
GrafikObjekt container = new GrafikObjekt("Container", 0, 0, 800, 600, "weiß");
GrafikObjekt button1 = new GrafikObjekt("Button", 10, 10, 100, 30, "blau");
GrafikObjekt button2 = new GrafikObjekt("Button", 120, 10, 100, 30, "grün");
container.addKind(button1);
container.addKind(button2);
System.out.println("Original Container: " + container);
GrafikObjekt geklonteContainer = container.clone();
geklonteContainer.verschieben(50, 50);
System.out.println("Geklonter Container: " + geklonteContainer);
System.out.println("Original nach Verschiebung: " + container);
// Registro de prototipos
System.out.println("\n--- Registro de prototipos ---");
PrototypeRegistry registry = new PrototypeRegistry();
// Registrar prototipos
registry.registrierePrototyp("bericht", new Dokument("Standard-Bericht", ""));
registry.registrierePrototyp("button", new GrafikObjekt("Button", 0, 0, 80, 25, "grau"));
// Clonar prototipos desde el registro
Dokument neuerBericht = registry.klonePrototyp("bericht");
neuerBericht.setTitel("Monatsbericht");
neuerBericht.setInhalt("Monatliche Statistiken...");
GrafikObjekt neuerButton = registry.klonePrototyp("button");
neuerButton.verschieben(200, 100);
System.out.println("Neuer Bericht: " + neuerBericht);
System.out.println("Neuer Button: " + neuerButton);
System.out.println("Verfügbare Prototypen: " + registry.getVerfuegbarePrototypen());
// Optimización de rendimiento
System.out.println("\n--- Optimización de rendimiento ---");
PerformancePrototypManager manager = new PerformancePrototypManager();
Dokument template = new Dokument("Template", "Vorlageninhalt");
// Muchos clones con optimización
long startZeit = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Dokument schnell = manager.getOptimiertesClone(Dokument.class, template);
schnell.setTitel("Dokument " + i);
}
long endZeit = System.currentTimeMillis();
System.out.println("1000 optimierte Klone: " + (endZeit - startZeit) + "ms");
System.out.println("Cache Größe: " + manager.getCacheSize());
}
}
Resumen de Patrones Creacionales
| Patrón | Propósito | Cuándo usar | Ventajas |
|---|---|---|---|
| Singleton | Garantizar una única instancia | Logger, configuración | Acceso global, eficiencia de memoria |
| Factory Method | Delegar la creación de objetos | Frameworks, plugins | Bajo acoplamiento, extensibilidad |
| Abstract Factory | Crear familias de objetos | Toolkits UI, bases de datos | Objetos consistentes |
| Builder | Construir objetos complejos paso a paso | Configuración, DSLs | Legibilidad, flexibilidad |
| Prototype | Crear objetos mediante clonación | Rendimiento, plantillas | Eficiencia de costos |
Listas de Verificación para Implementación
Singleton
- Constructor privado
- Instancia estática
- Thread-Safety
- Serialization-Safety
- Protección contra clonación
Factory Method
- Método factory abstracto
- Implementaciones concretas
- Jerarquía de productos
- Bajo acoplamiento
Abstract Factory
- Interfaz Factory
- Factories concretas
- Familias de productos
- Consistencia
Builder
- Fluent Interface
- Producto inmutable
- Validación
- Separación de requeridos y opcionales
Prototype
- Interfaz Cloneable
- Deep Clone
- Registro de prototipos
- Optimización de rendimiento
Ventajas e Inconvenientes
Ventajas de los Patrones Creacionales
- Flexibilidad: Adaptar fácilmente la creación de objetos
- Reutilización: Lógica de creación reutilizable
- Encapsulación: Ocultar lógica compleja
- Testabilidad: Facilitar mocking
- Mantenibilidad: Creación centralizada
Inconvenientes
- Complejidad: Clases e interfaces adicionales
- Overhead: Más código en casos simples
- Curva de aprendizaje: Entender los patrones requiere estudio
- Sobre-ingeniería: Riesgo de soluciones demasiado complejas
Preguntas Frecuentes en Exámenes
-
¿Cuándo usar Singleton en lugar de una clase estática? Singleton para características OO como herencia, interfaces e inicialización perezosa.
-
¿Cuál es la diferencia entre Factory Method y Abstract Factory? Factory Method crea un producto, Abstract Factory crea familias de productos.
-
Explica la ventaja del patrón Builder. Construcción paso a paso de objetos complejos con Fluent Interface y validación.
-
¿Cuándo es útil el patrón Prototype? Cuando la creación de objetos es costosa o necesitas muchos objetos similares.
Fuentes Principales
- https://refactoring.guru/design-patterns/creational-patterns
- https://www.oracle.com/technetwork/java/designpatterns-138485.html
- https://en.wikipedia.org/wiki/Creational_pattern
Lecturas Recomendadas: Design Patterns
Keine Bücher für Kategorie "design-patterns" gefunden.



