定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
落实到代码就是: 有一个类族A(继承与同一抽象类或者父类),它们各自的实现类之间又有许多不同的操作,或者也得考虑增加新的操作,有一个族群B将要访问A中许多对象,并且对不同类型的对象进行的操作不同,那么我们为了避免代码耦合以及变动引起的代码污染,就通过定义一个访问接口,来访问族群A,而A通过一个接口方法,将实例回传给族群B,族群B就可以拿到确定的对象来操作了,不用进行if.else判断,强制类型转换等操作,如果以后想加入新的一种访问对象,也只要增加接口方法就行了(如果需要频繁的增加,说明不适合)。
族群A:
/**
* 被访问者基类
* @author PC
*
*/
public abstract class Staff {
public String name;
public int kpi;
public Staff(String name){
this.name = name;
kpi = new Random().nextInt(10);
}
/**
* 为访问者提供访问的接口
* @param visitor
*/
public abstract void accept(Visitor visitor);
}
public class Engineer extends Staff {
public Engineer(String name) {
super(name);
}
/**
* 将自身传递给Visitor
*/
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
/**
* 代码数
* @return
*/
public int getCodeCount(){
return new Random().nextInt(10000);
}
}
public class Manager extends Staff {
public Manager(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
/**
* 产品数
* @return
*/
public int getProducets(){
return new Random().nextInt(10);
}
}
隔离接口:
public interface Visitor {
void visit(Engineer engineer);
void visit(Manager manager);
}
族群B:
public class CEOVisitor implements Visitor{
public void visit(Engineer engineer) {
System.out.println("工程师:" + engineer.name + "..kpi:" + engineer.kpi );
}
public void visit(Manager manager) {
System.out.println("产品经理:" + manager.name + "..kpi:" + manager.kpi + "...产品数:" + manager.getProducets());
}
}
public class CTOVisitor implements Visitor{
public void visit(Engineer engineer) {
System.out.println("工程师:" + engineer.name + "..kpi:" + engineer.kpi + "...代码数:" + engineer.getCodeCount());
}
public void visit(Manager manager) {
System.out.println("产品经理:" + manager.name + "..kpi:" + manager.kpi );
}
}
业务类:
public class Report {
List<Staff> list = new ArrayList<Staff>();
public Report() {
list.add(new Manager("张三丰"));
list.add(new Engineer("洪七公"));
list.add(new Engineer("中神通"));
list.add(new Engineer("郭靖"));
list.add(new Engineer("黄蓉"));
}
/**
* 将访问者传递给被访问者
* @param visitor
*/
public void showReport(Visitor visitor){
for (Staff staff : list) {
staff.accept(visitor);
}
}
}
调用端:
public class Client {
public static void main(String[] args) {
Report report = new Report();
System.out.println("经理查看:");
report.showReport(new CEOVisitor());
System.out.println("技术总监查看:");
report.showReport(new CTOVisitor());
}
}
结果:
经理查看:
产品经理:张三丰..kpi:0...产品数:2
工程师:洪七公..kpi:3
工程师:中神通..kpi:4
工程师:郭靖..kpi:4
工程师:黄蓉..kpi:8
技术总监查看:
产品经理:张三丰..kpi:0
工程师:洪七公..kpi:3...代码数:3437
工程师:中神通..kpi:4...代码数:191
工程师:郭靖..kpi:4...代码数:5970
工程师:黄蓉..kpi:8...代码数:7894