Factory Method 
Autentia - Buen Diseño
Intención 
“Define an interface for creating an object, but 
let subclasses decide which class to instantiate. 
Factory Method let a class defer instantiation to 
subclasses.” 
Gamma et. al
Diagrama de Clases clásico
¿Cuándo usarlo? 
● Abstraer a la clase cliente sobre qué clase concreta de 
una familia tiene que usar. 
● Delegar la decisión de qué clases se van a instanciar 
en las clases hijas. 
● Desacoplar la complejidad de la instanciación. 
● Como alternativa a los constructores (Static FM). 
● Para hacer más extensible la arquitectura.
Pero no debemos usarlo siempre 
Como todos los patrones: no se debe forzar su uso si no es 
necesario. 
● Necesitamos una familia de objetos sobre los que 
trabajar 
● Puede aumentar la complejidad de la aplicación 
introduciendo más niveles de indirección. 
● No caer en la tentación de aplicarlo por si en el futuro 
es necesario.
Tipos de Implementación 
En general hay 4 tipos de implementación 
1. Factoría padre abstracta que delega siempre en las 
Factorías hijas. 
2. Factoría padre que devuelve valor por defecto y casos 
especiales en Factorías Hijas. 
3. Factoría padre con tipo por parámetro. 
Y también: 
4. Variante: Static Factory Method.
Ejemplo 
Familia de productos “Pelota” para diferentes 
deportes. 
public abstract class Pelota { 
float diametro; 
float peso; 
String material; 
public abstract String getTipo(); 
//Getters y Setters... 
} 
public class BaloncestoPelota extends Pelota { 
public String getTipo() { 
return "pelota de Baloncesto"; 
} 
} 
public class FutbolPelota extends Pelota { 
public String getTipo() { 
return "una pelota de fútbol"; 
} 
} 
public class TenisPelota extends Pelota { 
public String getTipo() { 
return "pelota de tenis"; 
} 
} 
public class GenericaPelota extends Pelota { 
public String getTipo() { 
return "pelota genérica"; 
} 
}
Ejemplo 
Deportistas a los que asignar una pelota para 
su deporte. 
public class Deportista { 
String nombre; 
Pelota pelota; 
public Deportista(String nombre) { 
this.nombre = nombre; 
} 
public String getSaludo() { 
return "Hola, soy " + getNombre() + " y juego con una pelota de " 
+ getPelota().getTipo() + " que pesa " + getPelota().getPeso() 
+ " gramos"; 
} 
//Getters y Setters... 
}
Ejemplo 
Familia de fábricas que construyen productos 
pelota concreta en cada método (tipo 1) 
public interface FactoryPelotas { 
public Pelota create(); 
} 
public class FactoryBaloncestoPelotas implements 
FactoryPelotas { 
public Pelota create() { 
return new BaloncestoPelota(); 
} 
} 
public class FactoryFutbolPelotas implements 
FactoryPelotas { 
public Pelota create() { 
return new FutbolPelota(); 
} 
} 
public class FactoryTenisPelotas implements 
FactoryPelotas { 
public Pelota create() { 
return new TenisPelota(); 
} 
}
Ejemplo 
Main (Cliente que usa productos) 
public class main { 
public static void main(String[] args) { 
ArrayList<Deportista> deportistas = new ArrayList<Deportista>(); 
// Definición de deportistas 
Deportista baloncestoDep = new Deportista("Gasol"); 
Deportista futbolDep = new Deportista("Messi"); 
Deportista tenisDep = new Deportista("Nadal"); 
// Fábricas concretas 
baloncestoDep.setPelota(new FactoryBaloncestoPelotas().create()); 
futbolDep.setPelota(new FactoryFutbolPelotas().create()); 
tenisDep.setPelota(new FactoryTenisPelotas().create()); 
deportistas.add(baloncestoDep); 
deportistas.add(futbolDep); 
deportistas.add(tenisDep); 
for (Deportista dep : deportistas) { 
dep.getPelota().setPeso((float) Math.random() * 500); 
System.out.println( dep.getSaludo()); 
}} 
}
Factory con parámetro (tipo 3) 
public class FactoryParamPelotas { 
public static Pelota create(TipoPelota tipo) { 
Pelota salida; 
switch (tipo) { 
case BALONCESTO: 
salida = new BaloncestoPelota(); 
break; 
case TENIS: 
salida = new TenisPelota(); 
break; 
case FUTBOL: 
salida = new FutbolPelota(); 
break; 
default: 
salida = new GenericaPelota(); 
break; 
} 
return salida; 
} 
} 
…… 
baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.BALONCESTO)); 
baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.FUTBOL)); 
baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.TENIS));
Static Factory Method 
Método estático que sustituye al constructor 
Foo x = new Foo(); 
vs. 
Foo x = Foo.create(); 
...o usando parámetros en la superclase 
Foo x = Foo.create(tipo1); 
también mejora la legibilidad del código 
Punto punto = new Punto(x,y, sistemaMedicion); 
si lo cambiamos por 
Punto punto = Punto.createByMetros(x,y); 
Punto punto2 = Punto.createByInches(x,y);
Relación con Abstract Factory 
AF es un nivel superior de abstracción
Gracias!

Factory method

  • 1.
  • 2.
    Intención “Define aninterface for creating an object, but let subclasses decide which class to instantiate. Factory Method let a class defer instantiation to subclasses.” Gamma et. al
  • 3.
  • 4.
    ¿Cuándo usarlo? ●Abstraer a la clase cliente sobre qué clase concreta de una familia tiene que usar. ● Delegar la decisión de qué clases se van a instanciar en las clases hijas. ● Desacoplar la complejidad de la instanciación. ● Como alternativa a los constructores (Static FM). ● Para hacer más extensible la arquitectura.
  • 5.
    Pero no debemosusarlo siempre Como todos los patrones: no se debe forzar su uso si no es necesario. ● Necesitamos una familia de objetos sobre los que trabajar ● Puede aumentar la complejidad de la aplicación introduciendo más niveles de indirección. ● No caer en la tentación de aplicarlo por si en el futuro es necesario.
  • 6.
    Tipos de Implementación En general hay 4 tipos de implementación 1. Factoría padre abstracta que delega siempre en las Factorías hijas. 2. Factoría padre que devuelve valor por defecto y casos especiales en Factorías Hijas. 3. Factoría padre con tipo por parámetro. Y también: 4. Variante: Static Factory Method.
  • 7.
    Ejemplo Familia deproductos “Pelota” para diferentes deportes. public abstract class Pelota { float diametro; float peso; String material; public abstract String getTipo(); //Getters y Setters... } public class BaloncestoPelota extends Pelota { public String getTipo() { return "pelota de Baloncesto"; } } public class FutbolPelota extends Pelota { public String getTipo() { return "una pelota de fútbol"; } } public class TenisPelota extends Pelota { public String getTipo() { return "pelota de tenis"; } } public class GenericaPelota extends Pelota { public String getTipo() { return "pelota genérica"; } }
  • 8.
    Ejemplo Deportistas alos que asignar una pelota para su deporte. public class Deportista { String nombre; Pelota pelota; public Deportista(String nombre) { this.nombre = nombre; } public String getSaludo() { return "Hola, soy " + getNombre() + " y juego con una pelota de " + getPelota().getTipo() + " que pesa " + getPelota().getPeso() + " gramos"; } //Getters y Setters... }
  • 9.
    Ejemplo Familia defábricas que construyen productos pelota concreta en cada método (tipo 1) public interface FactoryPelotas { public Pelota create(); } public class FactoryBaloncestoPelotas implements FactoryPelotas { public Pelota create() { return new BaloncestoPelota(); } } public class FactoryFutbolPelotas implements FactoryPelotas { public Pelota create() { return new FutbolPelota(); } } public class FactoryTenisPelotas implements FactoryPelotas { public Pelota create() { return new TenisPelota(); } }
  • 10.
    Ejemplo Main (Clienteque usa productos) public class main { public static void main(String[] args) { ArrayList<Deportista> deportistas = new ArrayList<Deportista>(); // Definición de deportistas Deportista baloncestoDep = new Deportista("Gasol"); Deportista futbolDep = new Deportista("Messi"); Deportista tenisDep = new Deportista("Nadal"); // Fábricas concretas baloncestoDep.setPelota(new FactoryBaloncestoPelotas().create()); futbolDep.setPelota(new FactoryFutbolPelotas().create()); tenisDep.setPelota(new FactoryTenisPelotas().create()); deportistas.add(baloncestoDep); deportistas.add(futbolDep); deportistas.add(tenisDep); for (Deportista dep : deportistas) { dep.getPelota().setPeso((float) Math.random() * 500); System.out.println( dep.getSaludo()); }} }
  • 11.
    Factory con parámetro(tipo 3) public class FactoryParamPelotas { public static Pelota create(TipoPelota tipo) { Pelota salida; switch (tipo) { case BALONCESTO: salida = new BaloncestoPelota(); break; case TENIS: salida = new TenisPelota(); break; case FUTBOL: salida = new FutbolPelota(); break; default: salida = new GenericaPelota(); break; } return salida; } } …… baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.BALONCESTO)); baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.FUTBOL)); baloncestoDep.setPelota( FactoryParamPelotas.create(TipoPelota.TENIS));
  • 12.
    Static Factory Method Método estático que sustituye al constructor Foo x = new Foo(); vs. Foo x = Foo.create(); ...o usando parámetros en la superclase Foo x = Foo.create(tipo1); también mejora la legibilidad del código Punto punto = new Punto(x,y, sistemaMedicion); si lo cambiamos por Punto punto = Punto.createByMetros(x,y); Punto punto2 = Punto.createByInches(x,y);
  • 13.
    Relación con AbstractFactory AF es un nivel superior de abstracción
  • 14.