封裝一些做用於某種數據結構中的各元素的操做,它能夠在不改變這個暑假結構的前提下定義做用於這些元素的新的操做bash
##使用場景數據結構
##結構dom
visitor 接口或抽象類 定義了對每個元素訪問的行爲,它的參數就是能夠訪問的元素ide
ConcreteVisitor 具體訪問者 給出每個元素類訪問時產生的具體行爲函數
Element 元素接口或抽象接口 定義了一個接受訪問者的方法,其意義是指每一個元素都要能夠被訪問者訪問ui
ElementA、ElementB 具體元素類 提供接受訪問者的具體實現this
ObjectStructure 定義當中所提到的對象結果 它內部管理了元素集合,而且能夠迭代這些元素供訪問者訪問spa
##簡單實現code
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
複製代碼