I use the Visitor pattern all the time

The Visitor pattern is often maligned as too complex. I disagree. I use the visitor pattern all the time. I find it to be a very nice way to separate things that change for different reasons.
For example, let’s say I’ve got a list of employees and I want to create the following report of hourly employees:

Emp#NameQTD-hoursQTD-pay
1429Bob Martin432$22,576
1532James Grenning490 $28,776

I could simply add a method to the Employee class that produced that employee’s corresponding line on the report.

public class Employee {
  public abstract String reportQtdHoursAndPay();
}
public class HourlyEmployee extends Employee {
  public String reportQtdHoursAndPay() {
    //generate the line for this hourly employee
  }
}
public class SalariedEmployee extends Employee {
  public String reportQtdHoursAndPay() {} // do nothing
}

Then I could generate the report by iterating over all the Employee objects and calling reportQtdHoursAndPay().
The problem with this is that we have coupled the format and content of a report to the Employee object. This violates the Single Reponsibility Principle because it causes Employee to be changed every time the format or content of the report changes, or when any new reports are added.
To fix this, I can use the Visitor pattern as follows:

public class Employee {
  public abstract void accept(EmployeeVisitor v);
}
public class HourlyEmployee extends Employee {
  public void accept(EmployeeVisitor v) {
    v.visit(this);
  }
}
interface EmployeeVisitor {
  public void visit(HourlyEmployee he);
  public void visit(SalariedEmployee se);
}
public class QtdHoursAndPayReport implements EmployeeVisitor {
  public void visit(HourlyEmployee he) {
    // generate the line of the report.
  }
  public void visit(SalariedEmployee se) {} // do nothing
}

Now I can generate the report by creating a QtdHoursAndPayReport instance, and then iterating over all the Employee instances and calling accept and passing in the visitor:

  QtdHoursAndPayReport v = new QtdHoursAndPayReport();
  for (...) // each employee e
  {
    e.accept(v);
  }

This solves the Single Responsibility Principle by moving the report generation into a new object. Moreover, each new report will be added to a new derivative of EmployeeVisitor.
这个例子很好,其实要使用到访问者模式的地方都是有两个条件的,第一对于一群无关的类需要实施一类相同的算法;第二这群类必须要放到一个集合中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值