如有转载,请申明:
转载至 http://blog.youkuaiyun.com/qq_35064774/article/details/52075612
1 什么是访问者模式
访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这种操作需要修改的话,接受这个操作的数据结构则可以保持不变。
2 如何实现访问者模式
同样以一个简单的问题入手。
* 某公司有很多员工,作为老总,你可能会想知道一些他们的信息,比如每个人的月薪、年假时间、日工作时长等
很明显这个问题中数据结构相对稳定,但操作相对不定。这时候用访问者模式是比较合适的。
访问者模式实现相对比较复杂,这里先写测试类,以便能先了解访问者模式的用法。
package com.ittianyu.visitor;
public class Test {
public static void main(String[] args) {
Employees employees = new Employees();
employees.add(new Employee("Tom", 4000, 10, 8));
employees.add(new Employee("Bob", 9000, 40, 8));
SalaryVisitor sv = new SalaryVisitor();
employees.accept(sv);
System.out.println("");
VacationVisitor vv = new VacationVisitor();
employees.accept(vv);
System.out.println("");
WorkTimeVisitor wtv = new WorkTimeVisitor();
employees.accept(wtv);
}
}
测试类的代码是很简单的,先创建了一个员工集合类Employees,然后往里面加入了两个员工对象,之后创建分别创建了工资访问类SalaryVisitor、假期访问类VacationVisitor、工作时长访问类WorkTimeVisitor。
然后先设计Employee类。
package com.ittianyu.visitor;
public class Employee implements Visitable{
private String name;
private int salary;
private int vacation;
private int workTime;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getVacation() {
return vacation;
}
public void setVacation(int vacation) {
this.vacation = vacation;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
public Employee(String name, int salary, int vacation, int workTime) {
super();
this.name = name;
this.salary = salary;
this.vacation = vacation;
this.workTime = workTime;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
这个类只是简单的属性的get、set和构造方法。
这个类还实现了Visitable接口,在接口方法accept中,把自身作为参数传递给visitor的visit方法。这样做就可以方便的把访问操作和被访问者分离开。
这里补上接口的定义。
package com.ittianyu.visitor;
public interface Visitable {
void accept(Visitor visitor);
}
上面代码中还用到了Visitor类,这其实是一个接口,它里面只有一个visit方法。
package com.ittianyu.visitor;
public interface Visitor {
void visit(Employee employee);
}
有了Employee后,我们还需要一个能装该类的容器,因为公司不可能只有一个员工。
package com.ittianyu.visitor;
import java.util.ArrayList;
import java.util.List;
public class Employees implements Visitable{
private List<Employee> employees = new ArrayList<Employee>();
public void add(Employee employee) {
employees.add(employee);
}
public void remove(Employee employee) {
employees.remove(employee);
}
@Override
public void accept(Visitor visitor) {
for(int i = 0; i < employees.size(); i++)
employees.get(i).accept(visitor);
}
}
这个类含有容器的add和remove方法,同时还实现了Visitable,表明和员工类一样可以被访问者访问。
接着我们就需要定义访问者,毕竟没有访问者,我们如何访问呢。
package com.ittianyu.visitor;
public class SalaryVisitor implements Visitor {
@Override
public void visit(Employee employee) {
System.out.println(employee.getName() + " salary:" + employee.getSalary());
}
}
package com.ittianyu.visitor;
public class VacationVisitor implements Visitor {
@Override
public void visit(Employee employee) {
System.out.println(employee.getName() + " vacation:" + employee.getVacation());
}
}
package com.ittianyu.visitor;
public class WorkTimeVisitor implements Visitor {
@Override
public void visit(Employee employee) {
System.out.println(employee.getName() + " work time:" + employee.getWorkTime());
}
}
这三个访问者类,其实内部很简单,就是实现了访问者接口,在里面我们调用了员工类相应的方法来获取需要的信息。你会发现要增加新的操作很简单,就是新增一个访问者类。
到这里代码就都写完了,下面给出测试结果:
Tom salary:4000
Bob salary:9000
Tom vacation:10
Bob vacation:40
Tom work time:8
Bob work time:8
3 在什么情况下使用访问者模式
* 访问者模式仅应当在被访问者的类结构非常稳定的情况下使用。换言之,系统很少出现需要加入新节点的情况。
* 这些对象需要支持多线程,但又不想在同步化上耗费资源。
4 访问者模式的优点和缺点
优点:
* 访问者模式使得增加新的操作变得很容易。
* 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
* 访问者模式可以跨国这几个类的等级结构访问属于不同的等级结构的成员类。
* 积累状态。
缺点:
* 增加新的节点类变得困难。
* 破坏封装。