Este patrón se usa en los siguientes casos:
- Para evitar las subclases de un objeto creador como hace el patrón Abstract Factory.
- Para evitar el costo inherente a la creación de un objeto nuevo mediante el operador new cuando esto demasiado costoso para la aplicación.
Para implementar este patrón, se declara una clase base abstracta que tiene un método clone(). Cualquier clase que necesite un constructor deriva de la clase abstracta e implementa el método clone().
El cliente, en vez de escribir codigo que hace uso del operador new sobre una clase específica, llama al método clone() de la clase prototipo, o llama a un método factoría con un parámetro que especifica la clase deseada, o invoca el método clone() de la clase de alguna otra forma.
El siguiente diagrama UML representa este patrón:
Un ejemplo en Java de este patrón es el siguiente, sacado de la Wikipedia:
/** Prototype Class */
abstract class PrototypeFactory implements Cloneable {
public PrototypeFactory clone() throws CloneNotSupportedException {
// call Object.clone()
PrototypeFactory copy = (PrototypeFactory) super.clone();
//In an actual implementation of this pattern you might
//now change references to
//the expensive to produce parts from the copies
//that are held inside the prototype.
return copy;
}
abstract void prototypeFactory(int x);
abstract void printValue();
}
/** Concrete Prototypes to clone */
class PrototypeImpl extends PrototypeFactory {
int x;
public PrototypeImpl(int x) {
this.x = x;
}
@Override
void prototypeFactory(int x) {
this.x = x;
}
public void printValue() {
System.out.println("Value :" + x);
}
}
/** Client Class */
public class PrototypeExample {
private PrototypeFactory example;
// Could have been a private Cloneable example.
public PrototypeExample(PrototypeFactory example) {
this.example = example;
}
public PrototypeFactory makeCopy() throws CloneNotSupportedException {
return this.example.clone();
}
public static void main(String args[]) {
try {
PrototypeFactory tempExample = null;
int num = 1000;
PrototypeFactory prot = new PrototypeImpl(1000);
PrototypeExample cm = new PrototypeExample(prot);
for (int i = 0; i < 10; i++) {
tempExample = cm.makeCopy();
tempExample.prototypeFactory(i * num);
tempExample.printValue();
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
También se puede combinar el uso del patrón Prototype con el de Factory Method, como en el siguiente ejemplo, también extraído de la Wikipedia:
// Los productos deben implementar esta interface
public interface Producto extends Cloneable {
Object clone();
// Aqui van todas las operaciones comunes a los productos que genera la factoria
}
// Un ejemplo basico de producto
public class UnProducto implements Producto {
private int atributo;
UnProducto(int atributo) {
this.atributo = atributo;
}
public Object clone() {
return new UnProducto(this.atributo);
}
public String toString() {
return ((Integer)atributo).toString();
}
}
// La clase encargada de generar objetos a partir de los prototipos
public class FactoriaPrototipo {
private HashMap mapaObjetos;
private String nombrePorDefecto;
public FactoriaPrototipo() {
mapaObjetos = new HashMap();
// Se incluyen al mapa todos los productos prototipo
mapaObjetos.put("producto 1", new UnProducto(1));
}
public Object create() {
return create(nombrePorDefecto);
}
public Object create(String nombre) {
nombrePorDefecto = nombre;
UnProducto objeto = (UnProducto)mapaObjetos.get(nombre);
return objeto != null ? objeto.clone() : null;
}
}
public class PruebaFactoria {
static public void main(String[] args) {
FactoriaPrototipo factoria = new FactoriaPrototipo();
Producto producto = (Producto) factoria.create("producto 1");
System.out.println ("Este es el objeto creado: " + producto);
}
}
Referencias:
Prototype (patrón de diseño)
Prototype pattern
Prototype Pattern – Patron Prototipo — Patrones de diseño
Un ejemplo del Patrón Prototype ( la versión Java )
Pattern Summaries: Prototype
Prototype Design Pattern, UML diagram, Java Example
Otros patrones de diseño
Hola, ¿y como se haria esto mismo en un lenguaje que no soporte el metodo Clone()?
ResponderEliminarGracias saludos.