32 public class JuegoLaberintoEncantado extends JuegoLaberinto { public Habitacion crearHabitacion(int n) { return new HabitacionEncantada(n); } public Pared crearPared() { return new ParedEncantada(); } public Puerta crearPuerta( Habitacion h1, Habitacion h2) { return new PuertaEncantada(h1, h2); } } Ejemplo: Laberinto
33 Prototype (Prototipo) Propósito Especificar los tipos de objetos a crear utilizando una instancia prototípica, y crear nuevas instancias mediante copias del prototipo. Motivación GraphicTool es una clase dentro de un framework de creación de editores gráficos, que crea objetos gráficos, (instancias de subclases de Graphic) y los inserta en un documento, ¿cómo puede hacerlo si no sabe qué objetos gráficos concretos debe crear? Una instancia de GraphicTool es una herramienta de una paleta de herramientas y es inicializada con una instancia de Graphic: instancia prototípica.
34 Prototipo Aplicabilidad Cuando un sistema deba ser independiente de cómo sus productos son creados, compuestos y representados y: las clases a instanciar son especificadas en tiempo de ejecución, o para evitar crear una jerarquía de factorías paralela a la de productos, o cuando las instancias de una clase sólo pueden encontrarse en uno de un pequeño grupo de estados, o inicializar un objeto es costoso
35 Prototipo Consecuencias Al igual que con Builder y Factory Abstract oculta al cliente las clases producto concretas. Es posible añadir y eliminar productos en tiempo de ejecución: mayor flexibilidad que los anteriores. Reduce la necesidad de crear subclases.
36 Prototipo Consecuencias La composición reduce el número de clases que es necesario crear: “Definir nuevas clases sin programar” Definir nuevas clases mediante la creación de instancias de clases existentes. Definir nuevas clases cambiando la estructura. objetos compuestos actúan como clases
37 Prototipo Implementación Importante en lenguajes que no soportan el concepto de metaclase, así en Smalltalk o Java es menos importante. Usar un manejador de prototipos que se encarga del mantenimiento de una tabla de prototipos. Implementar la operación clone es lo más complicado. A veces se requiere inicializar el objeto creado mediante copia: prototipo con operaciones “set”
38 Ejemplo: Laberinto public class FactoriaPrototipoLaberinto { factoriaPrototipoLaberinto (Laberinto lab, Puerta p, Habitacion h, Pared m); { protoLab = lab; protoPuerta = p; protoHab = h; protoPared = m; }
public Laberinto makeLaberinto() {return (Laberinto)protoLab.clone(); }; public Pared makePared() { return (Pared) protoPared.clone(); }; public Habitacion makeHabitacion (int n) { Habitacion h = (Habitacion) protoHab.clone(); h.initialize(n); return h;} public Puerta makePuerta () (Habitacion h1, Habitacion h2) { Puerta p = (Puerta) protoPuerta.clone(); p.initialize(h1,h2); return p; } }
39 JuegoLaberinto juego; FactoriaPrototipoLaberinto laberintoSimple = new FactoriaPrototipoLaberinto (new Laberinto, new Puerta, new Habitacion, new Pared); Laberinto unlab = juego. makeLaberinto(laberintoSimple)
JuegoLaberinto juego; FactoriaPrototipoLaberinto otroLaberinto = new FactoriaPrototipoLaberinto (new Laberinto, new PuertaQueOye, new HabitacionEncantada, new Pared); Laberinto unlab = juego. makeLaberinto (otroLaberinto) Ejemplo: Laberinto
40 public class JuegoLaberinto { public Laberinto makeLaberinto (FactoriaPrototipoLaberinto factoria) { Laberinto unLab = factoria.makeLaberinto(); Habitacion h1 = factoria.makeHabitacion(1); Habitacion h2 = factoria.makeHabitacion(2); Puerta unaPuerta = factoria.makePuerta(h1,h2); unLab.addHabitacion(h1); unLab.addHabitacion(h2); h1.setLado(Norte, factoria.makePared() ); h1.setLado(Este, unaPuerta) .. h2.setLado(Oeste, unaPuerta); h2.setLado(Sur, factoria.makePared() ) return unLab; } } Ejemplo: Laberinto
41 Factoría Abstracta: Alternativa 1 Con métodos factoría
public abstract class WidgetFactory { public abstract Window createWindow(); public abstract Menu createScrollBar(); public abstract Button createButton(); }
public class MotifWidgetFactory extends WidgetFactory { public Window createWindow() {return new MotifWidow();} public ScrollBar createScrollBar() {return new MotifScrollBar();} public Button createButton() {return new MotifButton();} }
42 Factoría Abstracta: Alternativa 1
// Código cliente
WidgetFactory wf = new MotifWidgetFactory();
Button b = wf.createButton();
Window w = wf.createWindow(); …
43 Factoría Abstracta: Alternativa 2 Con prototipos
public class WidgetFactory { private Window protoWindow; private ScrollBar protoScrollBar; private Button protoButton; public WidgetFactory(Window wp, ScrollBar sbp, Button bf) { protoWindow = wp; protoScrollBar = sbp; protoButton = bp; }
public Window createWindow() {return (Window) protoWindow.clone(); } public ScrollBar createScrollBar() {return (ScrollBar) protoScrollBar.clone();} public Button createButton() {return (Button) protoButton.clone();} }
44 Factoría Abstracta: Alternativa 2 // crea objetos de una jerarquía de productos class FactoriaProductos { private Hashtable catalogo; public Producto getProducto(String s) { return (Producto) ((Producto) catalogo.get(s)).clone(); } public FactoriaProductos (String familia) { “inicializa el catalogo”} … }
45 Ejercicio Sea una herramienta para diseño y simulación de circuitos digitales que proporciona una paleta con elementos tales como puertas, diodos, interruptores, flip-flop,.., y que permite construir circuitos a partir de ellos. Los circuitos construidos por el usuario pueden ser añadidos a la paleta para ser utilizados directamente en la construcción de nuevos circuitos. Diseña una solución basada en patrones para el mecanismo de crear instancias de un nuevo circuito añadido a la paleta, describiendo la estructura de clases propuesta.
46 Singleton Propósito Asegurar que una clase tiene una única instancia y asegurar un punto de acceso global. Motivación Un manejador de ventanas, o un spooler de impresoras o de un sistema de ficheros o una factoría abstracta. La clase se encarga de asegurar que exista una única instancia y de su acceso.
47 Singleton Aplicabilidad Debe existir una única instancia de una clase, accesible globalmente. Consecuencias Acceso controlado a la única instancia Evita usar variables globales Generalizar a un número variable de instancias La clase Singleton puede tener subclases.
48 Singleton (Sin subclases) public class Singleton { public static Singleton getInstancia() { if (unicaInstancia == null) unicaInstancia = new Singleton(); return unicaInstancia; } private Singleton() { }
private static Singleton unicaInstancia = null; private int dato = 0; public int getDato() {return dato;} public void setDato(int i) {dato = i;} }
49 Ejemplo: Catálogo instancias prototípicas public class CatalogoCircuitos { public static CatalogoCircuitos getInstancia() { if (unicaInstancia == null) unicaInstancia = new CatalogoCircuitos(); return unicaInstancia; } private CatalogoCircuitos() { elems = new HashTable(); }
private static CatalogoCircuitos unicaInstancia = null; private Hashtable elems; public Circuito getCircuito(String id) { Circuito c = (Circuito) elems.get(id); return (Circuito) c.clone(); } public void addCircuito(String id,Circuito c) { elems.put(id,c); } }
Circuito sum = CatalogoCircuitos.getInstancia().getCircuito(“sumador”);
50 Singleton (Con subclases) public class FactoriaLaberinto { public static FactoriaLaberinto instancia(String s) { if (unicaInstancia == null) unicaInstancia = Class.forName(s).newInstance(); return unicaInstancia ; }
protected FactoriaLaberinto () { } … }
Página anterior | Volver al principio del trabajo | Página siguiente |