Patrones de Diseño LSUB, GSYC, URJC Tuesday, February 26, 13 Patrones de Diseño • Problemas comunes de programación • Una buena solución • Nombres para referirse a ellos Tuesday, February 26, 13 Iterator • Forma de recorrerse una colección • Oculta los detalles de cómo está implementado Tuesday, February 26, 13 Iterator public public Tuesday, February 26, 13 boolean hasNext(); Object next(); Iterator en Java • Las colecciones tienen un método iterator() que devuelve un Iterator • Hay un interfaz Iterable: public interface Iterable<T> { public Iterator<T> iterator(); } • Hay una construcción especial llamada foreach que actúa sobre iterables Tuesday, February 26, 13 Iterator en Java (azucar sintáctico) /* Bla implementa Iterable<T> */ Bla bs = new Bla(); for(Bla b: bs) System.out.println("bla:" + b); Tuesday, February 26, 13 Iterator en Java (equivalente) /* Bla implementa Iterable<Xbla> */ Bla bs = new Bla(); Iterator<Xbla> i = bs.iterator(); for(Xbla b = i.next(); i.hasNext(); b = i.next()) System.out.println("bla:" + b); Tuesday, February 26, 13 Iterator en Java • Tiene un método extra (opcional) public void remove(); Tuesday, February 26, 13 Visitor • Tengo una operación nueva • Para un grupo de clases en una estructura de datos • Quiero poder cambiar la implementación • Implemento un visitor Tuesday, February 26, 13 Visitor • El truco se basa en la sobrecarga de métodos • El visitor tiene un método muy sobrecargado • Una implementación para cada clase que visita Tuesday, February 26, 13 Visitor • Imaginemos que tenemos muchos tipos de figuras, Elipse, Círculo, Estrella... en un árbol • Y queremos representarlas de diferentes formas • De forma gráfica, en texto... • Para cada representación habría un Visitor • El visitor recorre el árbol visitando cada elemento Tuesday, February 26, 13 Visitor Tuesday, February 26, 13 Visitor • Todas las figuras deberían ser visitables: public interface Visitable { public } Tuesday, February 26, 13 void accept(Visitor visitor); Visitor • El visitor es el que hace el trabajo: public interface Visitor { public public public ... } Tuesday, February 26, 13 void visit(Elipse e); void visit(Estrella x); void visit(Tree t); Visitor • La figura llama al Visitor: public class Figura implements Visitable, Figura { ... @Override public void accept(Visitor visitor) { visitor.visit(this); } ... } Tuesday, February 26, 13 Visitor • La un árbol llama al Visitor: public class Figura implements Visitable, Tree { Tree right, left; Figura fig; @Override public void accept(Visitor visitor) { visitor.visit(this); } ... } Tuesday, February 26, 13 Visitor public class GraphicVisitor implements Visitor { @Override public void visit(Elipse e) { //dibujar elipse } @Override public void visit(Rectangulo r) { //dibujar rectangulo } @Override public void visit(Tree t) { visit(t.fig); visit(t.left); visit(t.right); } ... } Tuesday, February 26, 13 Factory • Creación de nuevos objetos • A partir de una descripción • Sin especificar la clase concreta Tuesday, February 26, 13 Factory • Imaginemos que leemos de un fichero • La descripción de una figura • No sabemos qué tipo de figura vamos a crear nombreFig = br.readLine(); Figura = new ????? Tuesday, February 26, 13 Factory public class FiguraFactory { ... public static Figura produce(String desc){ TipoFigura tf = TipoFigura.Valueof(desc); Figura f; switch(tf) { case ELIPSE: f = new Elipse(); break; case CIRCULO: f = new Circulo(); break; ... } } ... return tf; } Tuesday, February 26, 13 Factory • Ahora se puede crear una figura de la descripcion: f = FiguraFactory.produce(“circulo”); Tuesday, February 26, 13 Factory • Si vamos a crear muchos iguales, igual es mejor crear un objeto factoría de ese tipo: public class CirculoFactory { int r; Punto pos; CirculoFactory(int r, Punto pos) { rad = r; center = new Punto(pos.x, pos.y); } public Circulo produce(){ Circulo f = new Circulo(rad, center); break; } return f; } Tuesday, February 26, 13 Factory • Si vamos a crear muchos iguales, es mejor crear un objeto factoría de ese tipo. • La descripción se le da a la factoría y luego se producen como churros: circFact = new CirculoFactory(2, new Punto(2, 3)); circ = circFact.produce(); circ2 = circFact.produce(); Tuesday, February 26, 13 Prototype • Es un factory que clona objetos • A partir de uno dado Tuesday, February 26, 13 Singleton • Una única instancia del objeto • No tiene sentido que haya más de uno • Un método de clase devuelve la instancia Tuesday, February 26, 13 Singleton /* Sólo hay un universo!! */ public class Universo { ... private static final Universo universo = new Universo(0, 0); public static Punto getInstance() { return universo; } ... } Tuesday, February 26, 13 Façade • Interfaz unificado para un subsistema • Simplificar el uso • Desacoplar de detalles concretos Tuesday, February 26, 13 Façade class Cpu { public void freeze() { ... } public void jump(long position) { ... } public void execute() { ... } } class Memory { public void load(long position, byte[] data{ ... } } class HardDrive { public byte[] read(long lba, int size) { ... } } Tuesday, February 26, 13 Façade class Computer { private Cpu cpu; private Memory memory; private HardDrive hardDrive; public Computer() { this.cpu = new Cpu(); this.memory = new Memory(); this.hardDrive = new HardDrive(); } public void startComputer() { cpu.freeze(); memory.load(BOOT_ADDRESS, hardDrive.read(MBR, SECT_SIZE)); cpu.jump(BOOT_ADDRESS); cpu.execute(); } } Tuesday, February 26, 13 Façade class Usuario { public static void main(String[] args) { Computer facade = new Computer(); facade.startComputer(); } } Tuesday, February 26, 13 Wrapper/Adapter/ Decorator • Wrapper: envolver un objeto con otro • Si el wrapper es para cumplir un interfaz se llama Adapter • Para combinar funcionalidades se llama Decorator Tuesday, February 26, 13 Wrapper public interface TextFragment { public String getTexto(); } public class Capitulo implements TextFragment { private String texto; private int nCap; public String getTexto() { return "Capítulo " + nCap + ":\n" + texto; } } public class HtmlWrapper implements TextFragment { private TextFragment wrapped; public HtmlWrapper(TextFragment textF) { this.wrapped = textF; } public String getText() { return "<p>" + wrapped.getTexto() + "</p>"); } } Tuesday, February 26, 13 Observer • Tengo un conjunto de objetos interesados en cambios • Un objeto (Subject o sujeto) notifica a los Observer • En Java a los Observer se les suele llamar Listener Tuesday, February 26, 13 Observer • Imaginemos que tenemos un botón para cerrar la ventana • Queremos que se entere la ventana (para cerrarse) • Queremos que se entere la aplicación Tuesday, February 26, 13 Observer • Cuando alguien pinche en el botón de salir • Aviso a la ventana para que se cierre • Y a la aplicación para que salve el estado. Boton b = new Boton("salir"); b.register(ventana); b.register(aplicacion) Tuesday, February 26, 13 Observer interface Observer { public void update(Evento click); } interface Observable { public void register(Observer observer); public void dettach(Observer observer); public void notifyAll(); } Tuesday, February 26, 13 Observer class Boton implements Observable { private ArrayList<Observer> observers = new ArrayList<Observer>(); private bool pulsado; ... @Override public void register(Observer observer) { observers.add(observer); } @Override public void dettach(Observer observer) { observers.remove(observer); } @Override public void notifyAll() { for (Observer ob : observers) { ob.update(new Event(pulsado)); } } public void setPulsado(bool click) { pulsado = click; notifyObservers(); } } Tuesday, February 26, 13 Observer class Ventana implements Observer { ... @Override public void update(Event click) { ... exit(); } } class Applicacion implements Observer { ... @Override public void update(Event click) { ... saveState(); } } Tuesday, February 26, 13 Strategy/Command • Definir una familia de algoritmos • Con el mismo interfaz • Hacerlos intercambiables • En tiempo de ejecución se elige uno Tuesday, February 26, 13 Strategy/Command • Creas un Objeto y lo configuras • Un método execute() que hace el trabajo • Oculta la complejidad de la implementación Tuesday, February 26, 13 Strategy/Command File file = getFile(); FileBuf b = editorFactory.Load( file.size() ); b.edit(); Tuesday, February 26, 13 Strategy/Command interface FileBuf { public void muestra(); } class CargaDirecta implements FileBuf { ... public void edit() { // carga entero en un array (pequeño) } } class CargaEnDemanda implements Filebuf { ... public void edit() { // carga en demanda (si es grande) } } Tuesday, February 26, 13 Proxy • Objeto que representa a otro • Así se puede tener: • El objeto representado en otra máquina • Comprobar cosas adicionales antes de llamar al método • Tener una instancia compartida y varios representantes (el objeto es caro) Tuesday, February 26, 13 Model/View/Controller (MVC) • Tres tipos de componentes: • Controller: manda comandos al Model • Model: actualiza el View • View: presenta al usuario la información • El usuario manda su entrada al Controller y recibe la información del View Tuesday, February 26, 13