Factory Method
Propósito: Define una interfaz para crear un objeto, pero dejando en manos de las subclases la decisión de qué clase concreta instanciar.
Permite que una clase delegue en sus subclases la creación de objetos.
También conocido como: virtual constructor.
Motivación:
- Ej: un framework de aplicaciones debe poder presentar distintos tipos de documentos
- El framework maneja dos abstracciones:
Documento: los distintos tipos se definen como subclases
Aplicación: sabe cuándo crear un documento, pero no su tipo (no puede predecir el tipo de documento que el programador definirá).
- Solución:
Encapsular el conocimiento sobre qué subclase de Documento crear, y mover ese conocimiento fuera del framework.
Aplicabilidad:
Usa el patrón Factory method cuando:
- Una clase no puede prever la clase de objetos que tiene que crear.
- Una clase quiere que sus subclases decidan qué objetos crean.
- Las clases delegan responsabilidades a una de entre varias subclases auxiliares, y queremos localizar en qué subclase concreta se ha delegado.
Estructura:
Participantes:
- Product (Documento): define la interfaz de los objetos que crea el método factoría.
- ConcreteProduct (MiDocumento): implementa la interfaz de Product.
- Creator (Aplicación ):
Declara el método factoría que devuelve un objeto de tipo Product. Puede definir una implementación por defecto de dicho método, que devuelva un objeto de algún producto concreto ConcreteProduct.
Puede llamar al método factoría para crear un objeto de tipo Product.
- ConcreteCreator (MiAplicacion ): sobrescribe el método factoría para devolver un objeto de algún ConcreteProduct.
Colaboraciones:
El creator se apoya en sus subclases para definir el método de fabricación de manera que éste devuelva una instancia del ConcreteProduct adecuado.
Consecuencias:
- Elimina la necesidad de ligar clases específicas de una aplicación al código, que trata con la interfaz Product y funciona con cualquier clase ConcreteProduct.
- El cliente debe crear clases hijas de Creator para cada tipo de producto concreto
- Proporciona enganches para las subclases.
La creación de objetos con métodos factoría es más flexible
Las subclases pueden dar una versión extendida del código padre
- Conecta jerarquías de clases paralelas (delegación)
Implementación:
- Existen dos variantes principales:
Creator es una clase abstracta y no implementa el método factoría.
Creator es concreta y proporciona una implementación por defecto.
- Métodos factoría parametrizados: crean varios tipos de producto, identificados por un parámetro del método.
public class Creator {
public Product create (ProductId id) {
if (id==MINE) return new ProductA();
if (id==YOURS) return new ProductB();
return null;
}}
public class MyCreator extends Creator {
public Product create (ProductId id) {
if (id==MINE) return new ProductB();
if (id==YOURS) return new ProductA();
if (id==THEIRS) return new ProductC();
return super.create(id);
}}
Código de Ejemplo:
public class MazeGame {
// factory methods
Maze makeMaze () { return new Maze(); }
Wall makeWall () { return new Wall(); }
Room makeRoom (int n) { return new Room(n); }
Door makeDoor (Room r1, Room r2) { return new Door(r1, r2); }
// create maze
Maze createMaze () {
Maze aMaze = makeMaze();
Room r1 = makeRoom(1), r2 = makeRoom(2);
Door aDoor = makeDoor(r1, r2);
aMaze.addRoom(r1);
aMaze.addRoom(r2);
r1.setSide(Direction.NORTH, makeWall());
r1.setSide(Direction.EAST, aDoor);
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, aDoor);
return aMaze;
}}
// Podemos crear nuevos tipos de laberinto
public class BombedMazeGame extends MazeGame {
Wall makeWall () { return new BombedWall(); }
Room makeRoom (int n) { return new RoomWithABomb(n); }
}
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() { }
}
Usos conocidos:
- Frameworks que soportan aplicaciones MDI
- Creación de proxies en middlewares
- JDK. Clase URLConnection
Patrones relacionados:
- Abstract Factory. Se suele implementar con métodos fábrica.
- Template Method. Los métodos fábrica se suelen invocar desde métodos plantilla.
No hay comentarios:
Publicar un comentario