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