定义
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个暑假结构的前提下定义作用于这些元素的新的操作
使用场景
- 对象结构比较稳定,但经常需要再此对象上定义新的操作
- 需要对一个对象结构中的对象进行很多不同的并且不想关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在新增操作时修改这些类
结构
visitor 接口或抽象类
定义了对每一个元素访问的行为,它的参数就是可以访问的元素ConcreteVisitor 具体访问者
给出每一个元素类访问时产生的具体行为Element 元素接口或抽象接口
定义了一个接受访问者的方法,其意义是指每个元素都要可以被访问者访问ElementA、ElementB 具体元素类
提供接受访问者的具体实现ObjectStructure 定义当中所提到的对象结果
它内部管理了元素集合,并且可以迭代这些元素供访问者访问
简单实现
public interface Visitor {
void visit(Engineer engineer);
void visit(Manager manager);
}
Visitor定义了一个visitor接口,有2个visit函数,对于Engineer、Manager的访问会调用2个不同的方法,以此达到差异化处理
public abstract class Staff {
public String name;
public int kpi;
public Staff(String name) {
this.name = name;
kpi = new Random().nextInt(10);
}
public abstract void accept(Visitor visitor);
}
Staff为员工基类,定义了一个accept方法用来表示接受访问者访问,由子类具体实现
public class Manager extends Staff {
private int products;
public Manager(String name) {
super(name);
products = new Random().nextInt(10);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public int getProducts() {
return products;
}
}
Manager为经理类
public class Engineer extends Staff {
public Engineer(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
/**
* @return 工程师这一年的代码数量
*/
public int getCodeLines() {
return new Random().nextInt(10 * 10000);
}
}
Engineer为工程师类
public class CTOVisitor implements Visitor {
@Override
public void visit(Engineer engineer) {
System.out.println("工程师 :" + engineer.name + " , 代码行数" + engineer.getCodeLines());
}
@Override
public void visit(Manager manager) {
System.out.println("经理 :" + manager.name + " ,新产品数量 :" + manager.getProducts());
}
}
CTOVisitor为CTO访问者,关心技术贡献
public class CEOVisitor implements Visitor {
@Override
public void visit(Engineer engineer) {
System.out.println("工程师 :" + engineer.name + " , KPI" + engineer.kpi);
}
@Override
public void visit(Manager manager) {
System.out.println("经理 :" + manager.name + " , KPI" + manager.kpi + " ,新产品数量 :" + manager.getProducts());
}
}
CEOVisitor为CEO访问者 只关注业绩
public class BusinessReport {
List<Staff> mStaff = new LinkedList<>();
public BusinessReport() {
mStaff.add(new Manager("王经理"));
mStaff.add(new Engineer("工程师-Shawn.Xiong"));
mStaff.add(new Engineer("工程师-Kael"));
mStaff.add(new Engineer("工程师-Jack"));
mStaff.add(new Engineer("工程师-Rose"));
}
/**
* 为访问者展示报表
* @param visitor
*/
public void showReport(Visitor visitor) {
for (Staff staff : mStaff) {
staff.accept(visitor);
}
}
}
BusinessReport为员工业务报表,访问者可以通过showReport函数查看所有员工的业绩
public class Client {
public static void main(String[] args) {
BusinessReport report = new BusinessReport();
System.out.println("---------- 给 CEO 看的报表 -------------");
report.showReport(new CEOVisitor());
System.out.println("\n---------- 给 CTO 看的报表 -------------");
report.showReport(new CTOVisitor());
}
}
运行结果:
---------- 给 CEO 看的报表 -------------
经理 :王经理 , KPI0 ,新产品数量 :3
工程师 :工程师-Shawn.Xiong , KPI6
工程师 :工程师-Kael , KPI4
工程师 :工程师-Jack , KPI1
工程师 :工程师-Rose , KPI2
---------- 给 CTO 看的报表 -------------
经理 :王经理 ,新产品数量 :3
工程师 :工程师-Shawn.Xiong , 代码行数67720
工程师 :工程师-Kael , 代码行数37258
工程师 :工程师-Jack , 代码行数96044
工程师 :工程师-Rose , 代码行数3708