Si uso una llamada a Utils.calculaClave() desde mi clase y Utils cambia su función a Utils.calculaClave(boolean complejo), tendré que cambiar mi código y adaptarlo.
Si accedo a un atributo de otra clase y esa otra clase hace el atributo privado para protegerlo de cambios, tendré que cambiar mi código y adaptarlo.
public interface Visitable{
public void accept(Visitor visitor);
}
public interface Visitor{
public void visit(Visitable v);
//Visitable2 y OtroVisitable implementan Visitable
public void visit(Visitable2 v2);
public void visit(OtroVisitable v3);
}
public class Visitable2 {
public void accept(Visitor visitor) {
//Si no sabemos quién es, pasamos de él
}
//Amigo implementa Visitor
public void accept(Amigo visitor) {
//A este sí le dejo visitarme
visitor.visit(this);
}
}
public class OtroVisitable {
public void accept(Visitor visitor) {
//A mi en cambio me da igual
visitor.visit(this);
}
}
for(Visitable v : visitables) {
//cada visitable decide si acepta o no
//y si acepta, llama al "visit" del visitor
v.accept(visitor);
}
Decisión por parte del Visitable
Si añadimos nuevos Visitors, hay que modificar Visitable
Acoplamiento fuerte
Útil para recorrer elementos de forma genérica
//Todas nuestras estrategias hacen "do"
public interface IStrategy {
//Esta función puede ser cualquier cosa
public String do();
}
public class EstrategiaSimple implements IStrategy {
public String do() {
return "Y ya está. Hecho.";
}
}
public class EstrategiaComplicada implements IStrategy {
public String do() {
StringBuilder sb = new StringBuilder("Y");
sb.append(" ");
sb.append("ya está");
sb.append(". ");
sb.append("Hecho.");
return b.toString();
}
}
public class EstrategiaRara implements IStrategy {
public String do() {
StringBuilder sb = new StringBuilder("Pues");
sb.append(" yo");
sb.append(" devuelvo");
sb.append(" otra");
sb.append(" cosa.");
return b.toString();
}
}
//Clase super simple que ejecuta una estrategia según
//qué sea lo mejor ¡¡en tiempo real!!
public class Demo {
public static void main(String[] args) {
//Obtenemos la mejor estrategia
IStrategy strategy = getBestStrategy(args);
//No necesitamos saber la estrategia concreta para ejecutarla aquí
System.out.println(strategy.do());
}
}
//Clase super simple que ejecuta una estrategia según
//qué sea lo mejor ¡¡en tiempo real!!
public class Demo {
public static void main(String[] args) {
//Obtenemos la mejor estrategia
IStrategy strategy = getBestStrategy(args);
//No necesitamos saber la estrategia concreta para ejecutarla aquí
System.out.println(strategy.do());
}
}
Pero getBestStrategy,
¿lo implementamos nosotras?
Seguimos altamente acopladas
public class Demo {
public static void main(String[] args) {
//el constructor asigna una estrategia por defecto
Vendedor v = new Vendedor();
//pasan cosas en tu código
//en algún momento, alguien llama a algo como
v.setStrategy(new EstrategiaOptimaParaEsteCaso());
//pasan más cosas
//quizás la situación cambia y alguien llama otra vez
v.setStrategy(new OtraEstrategia());
//y finalmente, necesitamos ejecutar la estrategia
v.getStrategy().do();
}
}
public class Demo {
public static void main(String[] args) {
//el constructor asigna una estrategia por defecto
Vendedor v = new Vendedor();
//pasan cosas en tu código
//en algún momento, alguien llama a algo como
v.setStrategy(new EstrategiaOptimaParaEsteCaso());
//pasan más cosas
//quizás la situación cambia y alguien llama otra vez
v.setStrategy(new OtraEstrategia());
//y finalmente, necesitamos ejecutar la estrategia
v.getStrategy().do();
}
}
¿Qué tiene esto que ver con el visitor?
¿Qué tiene esto que ver con el visitor?
public class Casa implements Visitable {
public void accept(Visitor visitor) {
//Esto es spam, ni le abro
}
public void accept(Amigo visitor) {
visitor.visit(this);
}
}
public class Empresa implements Visitable {
public void accept(Visitor visitor) {
//Sí a todo
visitor.visit(this);
}
}
public class Demo {
public static void main(String[] args) {
List<Visitables> edificios;
Visitor vendedora = new Vendedora();
for(Visitable v : edificios) {
//cada visitable decide si acepta o no
//y si acepta, llama al "visit" del visitor
//como visitor mi estrategia está definida
v.accept(visitor);
}
}
}
public class EstrategiaAmable implements IStrategy {
public void visit(Visitable v) {
}
}
public class SugerAgresiva implements IStrategy {
public void visit(Visitable v) {
}
}
public class Demo {
public static void main(String[] args) {
List<Visitables> edificios;
Vendedora vendedora = new Vendedora(new DefaultStrategy());
if(esUnBarrioResidencial()) {
vendedora.setStrategy(new EstrategiaAmable());
}
if(estamosDeRebajas()) {
vendedora.setStrategy(new SuperAgresiva());
}
for(Visitable v : edificios) {
//El visitable no puede bloquearme
//soy yo quien decido hasta dónde llego
vendedora.getStrategy().visit(v);
}
}
}
¿Hacemos un triple salto mortal?
public class Demo {
public static void main(String[] args) {
List<Visitables> edificios;
Visitor vendedora = new Vendedora();
for(Visitable v : edificios) {
//cada visitable decide si acepta o no
//y si acepta, llama al "visit" de la vendedora
//como visitor mi estrategia está definida
v.accept(vendedora);
}
}
}
public class Demo {
public static void main(String[] args) {
List<Visitables> edificios;
Visitor vendedora = new Vendedora();
if(estamosDeRebajas()) {
vendedora.setStrategy(new SuperAgresiva());
}
for(Visitable v : edificios) {
//cada visitable decide si acepta o no
//y si acepta, llama al "visit" de la vendedora
//como vendedora mi estrategia es en tiempo real
v.accept(vendedora);
}
}
}
Esta presentación está en