FACTORY
METHOD
Edmundo Álvarez Jiménez
Antonio Fernández Alonso
Daniel López Ortega
Propósito:

Definir un interfaz para crear un objeto, pero dejando en manos de
las subclases la decisión de qué clase concreta instanciar.

Permite que una
instanciaciones.

También se le conoce como Virtual Constructor.
URJC
clase
delegue
SI - Factory Method
en
sus
subclases
las
2
Motivación:
Los frameworks usan clases abstractas para definir y
relacionar objetos, siendo a menudo encargados de crearlos.
Consideremos un framework para aplicaciones que puede
presentar varios documentos al usuario. Dos abstracciones claves
en este framework son las clases Application y Document. Los
clientes realizan implementaciones específicas de la aplicación
heredando de las clases anteriores, que son abstractas.
URJC
SI - Factory Method
3
La clase Application es responsable de gestionar Documents y
los creará cuando se necesiten.
URJC
SI - Factory Method
4
Application no puede predecir la subclase de Document que
debe instanciar, lo que crea un dilema:
“El framework debe instanciar clases,
pero sólo conoce clases abstractas que no puede instanciar”.
El patrón Factory Method lo soluciona encapsulando la
información de qué subclase Document debe crear, sacando ésta
del framework.
CreateDocument es un factory method porque es responsable
de “fabricar” un objeto.
URJC
SI - Factory Method
5
Aplicación:
Usamos el patrón factory method cuando:

Una clase no puede anticipar la clase de objetos que debe crear.

Una clase quiere que sus subclases especifiquen el objeto que ésta
crea.

Las clases delegan la responsabilidad a una de entre varias
subclases auxiliares, y queremos localizar qué subclase concreta es
en la que se delega.
URJC
SI - Factory Method
6
Estructura:
URJC
SI - Factory Method
7
Participantes:

Product (Document):


ConcreteProduct (MyDocument):


Define la interfaz de objetos que crea el factory method.
Implementa la interfaz Product.
Creator (Application):


Declara el factory method que devuelve un objeto de tipo Product.
Puede definir una implementación por defecto del factory method que devuelva
un objeto ConcreteProduct.
 Puede llamar al factory method para crear un objeto Product.

ConcreteCreator (MyApplication):

URJC
Redefine el factory method para devolver una instancia de un ConcreteProduct.
SI - Factory Method
8
Colaboraciones:
Creator depende de sus subclases para definir el factory
method de manera que éste devuelva una instancia del
ConcreteProduct apropiado.
URJC
SI - Factory Method
9
Consecuencias:
Factory method elimina la necesidad de ligar clases
específicas de la aplicación a nuestro código.
El código sólo trata con la interfaz de Product y puede trabajar
con cualquier ConcreteProduct definido por el usuario.
La desventaja del factory method es que los clientes podrían
tener que heredar de Creator sólo para crear un determinado objeto
de la clase ConcreteProduct.
URJC
SI - Factory Method
10
Estas son dos consecuencias adicionales del patrón factory method:

Proporciona conexión para las subclases:
Crear objetos dentro de una clase con un factory method es
más flexible que hacerlos directamente. Aporta a las subclases una
conexión para dar una extensión del objeto.

Conecta jerarquías de clases paralelas:
El factory method puede ser llamado por los clientes, en lugar
de por Creator.
Esto permite que el factory method pueda relacionar dos
jerarquías de clases paralelas.
URJC
SI - Factory Method
11
Implementación:
Al aplicar el patrón factory method encontramos varias cuestiones:

Dos variantes principales:

Cuando la clase Creator es abstracta y no proporciona una
implementación para el factory method que declara.



Cuando Creator no es abstracta y proporciona una implementación
predeterminada del factory method.


URJC
Las subclases definirán una implementación porque no hay un
comportamiento predeterminado razonable.
Hay que crear instancias de clases imprevisibles.
El Creator usa el factory method por flexibilidad.
Crea objetos en una operación aparte, para que las subclases puedan
redefinir el modo en que son creados. Asegurando poder cambiar la clase
de objetos que instancia la clase padre desde las subclases.
SI - Factory Method
12

Factory Methods Parametrizados:
Permiten crear varios tipos de productos, recibiendo un parámetro que
identifica el tipo de objeto a crear.
Todos los objetos creados por el método compartirán la interfaz Product.
class Creator{
public Product create(ProductId id){
if (id == MINE)
return new MyProduct();
if (id == YOURS)
return new YourProduct();
// repeat for remaining products...
return null;
}
}
class MyCreator extends Creator{
public Product create(ProductId id){
if (id == MINE)
return new MyProduct();
if (id == YOURS)
return new YourProduct();
if (id == THEIRS)
return new TheirProduct();
return super.create(id);
}
}
URJC
SI - Factory Method
13

Variantes y cuestiones específicas del lenguaje:
Lenguajes distintos a Java se prestan a otras variaciones.

Usar plantillas para evitar la herencia:
Un problema potencial del factory method es que puede
obligar a heredar sólo para crear los objetos Product apropiados.

Convenios de nominación:
Es conveniente usar convenios de nominación para aclarar
que estamos usando un factory method.
URJC
SI - Factory Method
14
Código de ejemplo:
El problema de CreateMaze es que codifica la clase del laberinto, las
habitaciones, las puertas y las paredes. Usando factory methods
permitimos a las subclases elegir estos componentes.
Usamos factory methods en MazeGame para crear los objetos
laberinto (maze), habitación (room), pared (wall) y puerta (door):
public class MazeGame{
MazeGame(){};
//factory methods:
Maze makeMaze(){
return new Maze();
}
Room makeRoom(int n){
return new Room(n);
}
Wall makeWall(){
return new Wall();
}
Door makeDoor(Room r1,Room r2){
return new Door(r1,r2);
}
Maze createMaze(){...}
}
URJC
SI - Factory Method
15
Cada factory method devuelve un componente del laberinto del tipo proporcionado.
MazeGame proporciona implementaciones por defecto que devuelven los tipos más
simples de laberintos, habitaciones, paredes y puertas.
Ahora podemos hacer que CreateMaze use estos factory method:
Maze CreateMaze(){
Maze aMaze = makeMaze();
Room r1 = makeRoom(1);
Room r2 = makeRoom(2);
Door theDoor = makeDoor(r1, r2);
aMaze.addRoom(r1);
aMaze.addRoom(r2);
r1.setSide(Direction.NORTH, makeWall());
r1.setSide(Direction.EAST, theDoor);
r1.setSide(Direction.SOUTH, makeWall());
r1.setSide(Direction.WEST, makeWall());
r2.setSide(Direction.NORTH, makeWall());
r2.setSide(Direction.EAST, makeWall());
r2.setSide(Direction.SOUTH, makeWall());
r2.setSide(Direction.WEST, theDoor);
return aMaze;
}
URJC
SI - Factory Method
16
Distintos juegos pueden heredar de MazeGame para especializar
partes del laberinto.
Las clases de MazeGame pueden redefinir algunos o todos los
factory methods para especificar variaciones en los productos. Por
ejemplo, un BombedMazeGame puede redefinir los productos Room y
Wall para devolver sus variantes con bomba:
public class BombedMazeGame extends MazeGame{
Wall makeWall(){
return new BombedWall();
}
Room makeRoom(int n){
return new RoomWithABomb(n);
}
}
URJC
SI - Factory Method
17
Se podría definir una variante EnchantedMazeGame como sigue:
public class EnchantedMazeGame extends MazeGame{
Room makeRoom(int n){
return new EnchantedRoom(n, CastSpell());
}
Door makeDoor(Room r1, Room r2){
return new DoorNeedingSpell(r1, r2);
}
protected Spell castSpell(){...}
}
URJC
SI - Factory Method
18
Patrones relacionados:
El Abstract Factory suele implementarse con Factory Methods.
Los Factory Method suelen llamarse desde Template Methods.
URJC
SI - Factory Method
19
Descargar

FACTORY METHOD