Skip to content

Instantly share code, notes, and snippets.

@jcfrank
Last active August 29, 2015 14:03
Show Gist options
  • Save jcfrank/53e8dcddd350af209881 to your computer and use it in GitHub Desktop.
Save jcfrank/53e8dcddd350af209881 to your computer and use it in GitHub Desktop.
Visitor pattern -- my understanding

Roles

  • Visitor interface

    Defines visit methods for all types that could be visited.

  • Visitor implementations

    Defines visit behavior for different types.

  • Element interface

    Defines accept method to accept visitor interface.

  • Element implementations

    Accept visitor and invoke its visit behavior. May include some conditionto decide whether to accept the visitor.

  • Element collections

    Collection of element interfaces. Iterate element and invoke their accept behavior.

Benefits

When we need to add new behaviors to elements. We can simply define new visitor imlementations with new visit behaviors. So element classes don't have to be changed.

Sample

C# real life example

Groovy example

/*
 * visitor.groovy
 */

interface Visitor {
    void visit(Employee employee)
    void visit(Boss boss)
}

interface Element {
    void accept(Visitor visitor)
}

class Employee implements Element {
    private int payment = 22000
    private int vacation = 0
    private String name
    private boolean inOffice = true

    public Employee(String name) {
        this.name = name
    }

    public void accept(Visitor visitor) {
        if (inOffice) {
            visitor.visit(this)
        }
    }

    public int getPayment() {
        return payment
    }
    public void setPayment(int payment) {
        this.payment = payment
    }

    public int getVacation() {
        return vacation
    }
    public void setVacation(int vacation) {
        this.vacation = vacation
    }

    public String getName() {
        return name
    }

    public void leaveOffice() {
        inOffice = false
    }
}

class Boss implements Element {

    @Override
    void accept(Visitor visitor) {
        visitor.visit(this)
    }
}

class PaymentVisitor implements Visitor {
    public void visit(Employee employee) {
        employee.setPayment(employee.getPayment() + 3000)
    }

    @Override
    void visit(Boss boss) {
        //do something
    }
}

class VacationVisitor implements Visitor {
    public void visit(Employee employee) {
        employee.setVacation(employee.getVacation() + 3)
    }

    @Override
    void visit(Boss boss) {
        //do something
    }
}

class Employees {
    private LinkedList<Employee> _employees = new LinkedList<>()

    public accpet(Visitor visitor) {
        for (def employee : _employees) {
            employee.accept(visitor)
        }
    }

    public void add(Employee employee) {
        _employees.add(employee)
    }

    public String getVacationAndPayment() {
        StringBuilder builder = new StringBuilder()
        for (def employee : _employees) {
            builder.append("name: " + employee.getName())
            builder.append("\n")
            builder.append("payment: " + employee.getPayment())
            builder.append("\n")
            builder.append("vacation: " + employee.getVacation())
            builder.append("\n")
        }
        return builder.toString()
    }
}

def main() {
    def emplyees = new Employees()
    def dude = new Employee("Dude")
    emplyees.add(new Employee("John"))
    emplyees.add(new Employee("Mary"))
    emplyees.add(dude)
    println(emplyees.getVacationAndPayment())

    println(dude.getName() + " left the office!\n")
    dude.leaveOffice()

    println("Here comes the PaymentVisitor!")
    emplyees.accpet(new PaymentVisitor())
    println("Here comes the VacationVisitor!")
    emplyees.accpet(new VacationVisitor())
    println(emplyees.getVacationAndPayment())
}

main()

Result

name: John
payment: 22000
vacation: 0
name: Mary
payment: 22000
vacation: 0
name: Dude
payment: 22000
vacation: 0

Dude left the office!

Here comes the PaymentVisitor!
Here comes the VacationVisitor!
name: John
payment: 25000
vacation: 3
name: Mary
payment: 25000
vacation: 3
name: Dude
payment: 22000
vacation: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment