代码语言:javascript复制
public abstract class Employee {
// 抽象的员工类,有自己的一些属性
private String name;
private int salary;
// getter/setter
// 提供一个方法,输出员工信息
public final void report(){
String info = "姓名:" name "t薪水:" salary "t";
info = info this.getOtherInfo(); // 一个钩子,子类提供他自己的信息
System.out.println(info);
}
//子类去实现自己独有的信息
protected abstract String getOtherInfo();
}
// 普通员工
public class CommonEmployee extends Employee {
private String job;
// getter/setter
// 普通员工独特的信息就是提供自己的工作是什么
protected String getOtherInfo() {
return "工作:" job "t";
}
}
// 经理
public class Manager extends Employee {
private String performance;
// 经理提供的信息就是业绩
protected String getOtherInfo(){
return "业绩:" this.performance "t";
}
}
这个问题是外部场景只能调用 report 输出信息,能输出的信息也都是子类设计时定好的。如同邀请朋友来家参观,参观后,不同的人有不同的描述,这个例子挺好的,用现在的方式不好弄。
所以有了访问者模式,提供一个 Visitor。
代码语言:javascript复制// 这麻烦的是要为每个子类单独写方法,因为不同子类要 report 的内容是不同的
public interface IVisitor {
public void visit(CommonEmployee commonEmployee);
public void visit(Manager manager);
}
// 将原来 Manager 自己维护的 report 和 getOtherInfo 都放到 Visitor 里
public class Visitor implements IVisitor {
public void visit(CommonEmployee commonEmployee) {
System.out.println(this.getCommonEmployee(commonEmployee));
}
public void visit(Manager manager) {
System.out.println(this.getManagerInfo(manager));
}
private String getBasicInfo(Employee employee){
return "姓名:" name "t薪水:" salary "t";
}
private String getManagerInfo(Manager manager){
String basicInfo = this.getBasicInfo(manager);
String otherInfo = "业绩:" manager.getPerformance() "t";
return basicInfo otherInfo;
}
private String getCommonEmployee(CommonEmployee commonEmployee){
String basicInfo = this.getBasicInfo(commonEmployee);
String otherInfo = "工作:" commonEmployee.getJob() "t";
return basicInfo otherInfo;
}
}
代码语言:javascript复制public abstract class Employee {
// 抽象的员工类,有自己的一些属性
private String name;
private int salary;
// getter/setter
// 接收一个访问者
protected abstract void accept(IVisitor visitor);
}
public class CommonEmployee extends Employee {
private String job;
@Override
public void accept(IVisitor visitor){
// 一接收一个访问者就输出了自己的信息描述
visitor.visit(this);
}
}
要输出信息,原来调用 Emplyee 的 report,现在调用 accept,参数传进来一个 Visitor。主要的优点就是如果修改输出内容,不需要修改 Employee 这些子类,只需要修改访问者,但是同样在修改类,修改访问者也没觉得比修改被访问者高级。
应该说在一个项目中,Employee 肯定在许多地方都使用到,对于它的修改可能牵一发而动全身。而 Visitor 是专门创造出来为 Employee 服务的,所以修改它不会有太大的影响。
缺点是两者联系笔记紧密,Visitor 知道 Employee 的细节,如果 Employee 的属性改了,Visitor 也要修改,但是 Visitor 作为专门为 Employee 服务的仆人,倒也符合直觉。
然后职责单一,输出的职责单独一个类去负责。