《设计模式》一书对于访问者模式给出的定义为:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。从定义可以看出结构对象是使用访问者模式必须条件,而且这个结构对象必须存在遍历自身各个对象的方法。这便类似于java中的collection概念了。
以下是访问者模式的组成结构:
抽象访问者(Visitor)角色:定义接口,声明一个或多个访问操作。
具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象元素(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
具体元素结点(ConcreteElement)角色:实现抽象结点所规定的接受操作。
数据结构对象(ObjectStructure)角色:可以遍历结构中的所有元素,提供一个接口让访问者对象都可以访问每一个元素。
来张类图就能更加清晰的看清访问者模式的结构了。
以下是设计模式之禅示例代码:
public interface IVisitor {
//首先定义我可以访问普通员工
public void visit(CommonEmployee commonEmployee);
//其次定义,我还可以访问部门经理
public void visit(Manager manager);
}
public abstract class Employee {
public final static int MALE = 0; //0代表是男性
public final static int FEMALE = 1; //1代表是女性
//甭管是谁,都有工资
private String name;
//只要是员工那就有薪水
private int salary;
//性别很重要
private int sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getSalary() {
return salary;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSex() {
return sex;
}
//我允许一个访问者过来访问
public abstract void accept(IVisitor visitor);
}
public class Visitor implements IVisitor {
private String getBasicInfo(Employee employee) {
String info = "姓名:"+employee.getName()+"\t";
info = info + "性别:" + (employee.getSex() == Employee.FEMALE?"女":"男") + "\t";
info = info + "薪水:" + employee.getSalary() + "\t";
return info;
}
@Override
public void visit(CommonEmployee commonEmployee) {
// TODO Auto-generated method stub
System.out.println(this.getCommonEmployee(commonEmployee));
}
private String getCommonEmployee(CommonEmployee commonEmployee) {
// TODO Auto-generated method stub
String basicInfo = this.getBasicInfo(commonEmployee);
String otherInfo = "工作:"+commonEmployee.getJob()+"\t";
return basicInfo + otherInfo;
}
@Override
public void visit(Manager manager) {
// TODO Auto-generated method stub
System.out.println(this.getManagerInfo(manager));
}
private String getManagerInfo(Manager manager) {
// TODO Auto-generated method stub
String basicInfo = this.getBasicInfo(manager);
String otherInfo = "业绩:"+manager.getPerformance() + "\t";
return basicInfo + otherInfo;
}
}
public class CommonEmployee extends Employee {
//工作内容,这个非常重要,以后的职业规划就是靠这个了
private String job;
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public void accept(IVisitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
public class Manager extends Employee {
//这类人物的职责非常明确:业绩
private String performance;
@Override
public void accept(IVisitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
public void setPerformance(String performance) {
this.performance = performance;
}
public String getPerformance() {
return performance;
}
}
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for(Employee emp:mockEmployee()){
emp.accept(new Visitor());
}
}
private static List<Employee> mockEmployee() {
List<Employee> empList = new ArrayList<Employee>();
//产生张三这个员工
CommonEmployee zhangSan = new CommonEmployee();
zhangSan.setJob("编写Java程序,绝对的蓝领、苦工加搬运工");
zhangSan.setName("张三");
zhangSan.setSalary(1800);
zhangSan.setSex(Employee.MALE);
empList.add(zhangSan);
//产生李四这个员工
CommonEmployee liSi = new CommonEmployee();
liSi.setJob("页面美工,审美素质太不流行了!");
liSi.setName("李四");
liSi.setSalary(1900);
liSi.setSex(Employee.FEMALE);
empList.add(liSi);
//再产生一个经理
Manager wangWu = new Manager();
wangWu.setName("王五");
wangWu.setPerformance("基本上是负值,但是我会拍马屁呀");
wangWu.setSalary(18750);
wangWu.setSex(Employee.MALE);
empList.add(wangWu);
return empList;
}
}
打印结果:
姓名:张三性别:男 薪水:1800 工作:编写Java程序,绝对的蓝领、苦工加搬运工
姓名:李四性别:女 薪水:1900 工作:页面美工,审美素质太不流行了!
姓名:王五性别:男 薪水:18750 业绩:基本上是负值,但是我会拍马屁呀