Skip to content

Commit

Permalink
Add Visitor pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
peterm85 committed Nov 22, 2019
1 parent 3945b74 commit b4f0c3d
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 1 deletion.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Forma en que las clases u objetos interaccionan y distribuyen funcionalidades.
* [Mediator](#mediator) [**O**]
* [Template method](#template) [**C**]
* [Iterator](#iterator) [**O**]
* [Visitor] [**O**]
* [Visitor](#visitor) [**O**]
* [State] [**O**]
* [Interpreter] [**C**]

Expand Down Expand Up @@ -420,3 +420,22 @@ Primero(), Siguiente(), HayMas() y ElementoActual().
* [Notifications](https://github.com/peterm85/design-patterns/tree/master/src/iterator/examples/notifications)

**Referencia:** [https://www.geeksforgeeks.org/iterator-pattern/](https://www.geeksforgeeks.org/iterator-pattern/)

## <a name="visitor">Visitor</a> [&#8593;](#lista-de-patrones)

**Propósito:** Separar el algoritmo de la estructura de un objeto.

La idea básica es que se tiene un conjunto de clases elemento que conforman la *estructura* de un objeto. Cada una de estas clases elemento tiene un método aceptar (accept()) que recibe al objeto visitante (visitor) como argumento. El visitante es una interfaz que tiene un método visit diferente para cada clase elemento; por tanto habrá implementaciones de la interfaz visitor de la forma: visitorClase1, visitorClase2... visitorClaseN. El método accept de una clase elemento llama al método visit de su clase.

Si hay demasiadas implementaciones de la interface visitor, se hace dificil extender.

**Aplicación:** Usamos el patrón Visitor cuando ...
* Se desea mover la lógica operacional desde los objetos a otra clase.
* Se desea definir una operación sobre objetos de una jerarquía de clases sin modificar las clases sobre las que opera.
* Se desea representar una operación que se realiza sobre los elementos que conforman la estructura de un objeto
* Teniendo un buen número de instancias de un pequeño número de clases, se desea realizar alguna operación que involucra a todas o a la mayoría de ellas.

**Ejemplos:**
* [Airport Security Control](https://github.com/peterm85/design-patterns/tree/master/src/visitor/examples/airportsecuritycontrol)
* [Arithmetic](https://github.com/peterm85/design-patterns/tree/master/src/visitor/examples/arithmetic)

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package visitor.examples.airportsecuritycontrol;

import java.util.List;

public class InternationalPassenger implements Passenger{
private String passport;
private Boolean visa;
private List<String> belongings;

public InternationalPassenger(String passport, Boolean visa, List<String> belongings) {
this.passport = passport;
this.visa = visa;
this.belongings = belongings;
}

public String getPassport() {
return passport;
}

public Boolean getVisa() {
return visa;
}

public List<String> getBelongings() {
return belongings;
}

@Override
public boolean accept(PoliceOfficer visitor) {
return visitor.visit(this);
}
}
26 changes: 26 additions & 0 deletions src/visitor/examples/airportsecuritycontrol/NationalPassenger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package visitor.examples.airportsecuritycontrol;

import java.util.List;

public class NationalPassenger implements Passenger{
private String identityDocument;
private List<String> belongings;

public NationalPassenger(String identityDocument, List<String> belongings) {
this.identityDocument = identityDocument;
this.belongings = belongings;
}

public String getIdentityDocument() {
return identityDocument;
}

public List<String> getBelongings() {
return belongings;
}

@Override
public boolean accept(PoliceOfficer visitor) {
return visitor.visit(this);
}
}
5 changes: 5 additions & 0 deletions src/visitor/examples/airportsecuritycontrol/Passenger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package visitor.examples.airportsecuritycontrol;

public interface Passenger {
boolean accept(PoliceOfficer visitor);
}
31 changes: 31 additions & 0 deletions src/visitor/examples/airportsecuritycontrol/PoliceOfficer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package visitor.examples.airportsecuritycontrol;

import java.util.List;

public class PoliceOfficer {

public boolean visit(NationalPassenger passenger) {
boolean checked=false;
if(checkIdentification(passenger.getIdentityDocument()) && checkBelongings(passenger.getBelongings())) {
checked=true;
}

return checked;
}

private boolean checkIdentification(String id) {
return id!=null && !id.equals("");
}

private boolean checkBelongings(List<String> belongings) {
return !belongings.contains("Liquids");
}

public boolean visit(InternationalPassenger passenger) {
boolean checked=false;
if(checkIdentification(passenger.getPassport()) && checkBelongings(passenger.getBelongings()) && passenger.getVisa()) {
checked=true;
}
return checked;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package visitor.examples.airportsecuritycontrol;

import java.util.Arrays;
import java.util.Collections;

public class SecurityControlClient {

public static void main(String[] args) {
Passenger[] passengers = new Passenger[] {new NationalPassenger("45874005H", Arrays.asList("Coins","Bag","Sun glasses")),
new NationalPassenger(null, Collections.EMPTY_LIST),
new InternationalPassenger("4A4585BC", true, Arrays.asList("Cap","False beard","Gun")),
new InternationalPassenger("11AB8564", false, Arrays.asList("Suitcase","Coat")),
new InternationalPassenger("269LZF74", false, Arrays.asList("Liquids"))};

PoliceOfficer officer = new PoliceOfficer();

for(Passenger p: passengers) {
if(p.accept(officer)) {
System.out.println("Access granted");
}else {
System.out.println("Access NOT granted");
}
}
}
}
18 changes: 18 additions & 0 deletions src/visitor/examples/arithmetic/Client.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package visitor.examples.arithmetic;

public class Client {

public static void main(String argv[]) {
// Construcción de una expresión (a+5)*(b+1)
Expression expresion = new Mult( new Sum( new Variable("a"),
new Constant(5) ),
new Sum( new Variable("b"),
new Constant(1) ));

VisitorExpression expr = new VisitorExpression();
expresion.aceptar(expr);

// Visualizacion de resultados
System.out.println("Resultado: " + expr.obtenerResultado());
}
}
13 changes: 13 additions & 0 deletions src/visitor/examples/arithmetic/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package visitor.examples.arithmetic;

public class Constant extends Expression {
int _valor;

public Constant(int valor) {
_valor = valor;
}

public void aceptar(VisitorExpression v) {
v.visitConstant(this);
}
}
5 changes: 5 additions & 0 deletions src/visitor/examples/arithmetic/Expression.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package visitor.examples.arithmetic;

public abstract class Expression {
abstract public void aceptar(VisitorExpression v);
}
11 changes: 11 additions & 0 deletions src/visitor/examples/arithmetic/Mult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package visitor.examples.arithmetic;

public class Mult extends OpBinary {
public Mult(Expression izq, Expression der) {
super(izq, der);
}

public void aceptar(VisitorExpression v) {
v.visitMult(this);
}
}
9 changes: 9 additions & 0 deletions src/visitor/examples/arithmetic/OpBinary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package visitor.examples.arithmetic;

public abstract class OpBinary extends Expression {
Expression _izq, _der;

public OpBinary(Expression izq, Expression der) {
_izq = izq; _der = der;
}
}
11 changes: 11 additions & 0 deletions src/visitor/examples/arithmetic/Sum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package visitor.examples.arithmetic;

public class Sum extends OpBinary {
public Sum(Expression izq, Expression der) {
super(izq, der);
}

public void aceptar(VisitorExpression v) {
v.visitSum(this);
}
}
13 changes: 13 additions & 0 deletions src/visitor/examples/arithmetic/Variable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package visitor.examples.arithmetic;

public class Variable extends Expression {
String _variable;

public Variable(String variable) {
_variable = variable;
}

public void aceptar(VisitorExpression v) {
v.visitVariable(this);
}
}
36 changes: 36 additions & 0 deletions src/visitor/examples/arithmetic/VisitorExpression.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package visitor.examples.arithmetic;

public class VisitorExpression {

private String _resultado;

public void visitVariable(Variable v) {
_resultado = v._variable;
}

public void visitConstant(Constant c) {
_resultado = String.valueOf(c._valor);
}

private void visitOpBinary(OpBinary op, String pOperacion) {
op._izq.aceptar(this);
String pIzq = obtenerResultado();

op._der.aceptar(this);
String pDer = obtenerResultado();

_resultado = "(" + pIzq + pOperacion + pDer + ")";
}

public void visitSum(Sum s) {
visitOpBinary(s, "+");
}

public void visitMult(Mult m) {
visitOpBinary(m, "*");
}

public String obtenerResultado() {
return _resultado;
}
}

0 comments on commit b4f0c3d

Please sign in to comment.