访问者模式定义
访问者模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,在不改变数据结构的前提下定义一些新的操作。
访问者模式将对数据的操作,与数据结构进行分离,是行为类模式中最复杂的一种模式。
访问者模式作用
访问者模式作用:简单来说访问者模式主要的作用就是将“数据结构”和“数据操作”进行分离,解决这两者之间耦合性的问题。
访问者模式角色
访问者模式实现的关键:是如何将作用于元素的操作分离出来封装成独立的类。
访问者模式的基本结构,包含以下主要角色,如下图所示:
1. Vistor(抽象访问者)
定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素,就好像是王者荣耀里面不同的玩家。
2. ConcreteVisitor(具体访问者)
每个具体访问者都实现了Vistor中定义的操作,就好比是具体某一个玩家。
3. Element(抽象元素)
声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数,可以类比成王者里面英雄的模板。
4.ConcreteElement(具体元素)
实现了Element中的accept()方法,调用Vistor的访问方法以便完成对一个元素的操作,可以表示为具体某一个英雄,好比是庄周和甄姬。
5. ObjectStructure(对象结构)
可以是组合模式,也可以是集合,是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
访问者模式类图如下:
访问者模式案例
访问者模式的KPI考核的代码示例,具体会包含如下的角色:
1.抽象元素:Employee
public abstract class Employee { public String name; public int kpi; //员工KPI public Employee(String name) { this.name = name; kpi = new Random().nextInt(10); } //接收访问者的访问 public abstract void accept(Visitor visitor); }
2.抽象访问者:Visitor
public interface Visitor { void visit(Engineer engineer); void visit(Manager manager); }
3.具体元素:Engineer
public class Engineer extends Employee { public Engineer(String name) { super(name); } @Override public void accept(Visitor visitor) { visitor.visit(this); } //考核指标是每年的代码量 public int getCodeLines() { return new Random().nextInt(10 * 10000); } }
4.具体元素:Manager
public class Manager extends Employee { public Manager(String name) { super(name); } @Override public void accept(Visitor visitor) { visitor.visit(this); } //考核的是每年新产品研发数量 public int getProducts() { return new Random().nextInt(10); } }
5.具体访问者:CEOVisitor
public class CEOVisitor implements Visitor { @Override public void visit(Engineer engineer) { System.out.println("工程师" engineer.name ",KIP:" engineer.kpi); } @Override public void visit(Manager manager) { System.out.println("经理:" manager.name ",KPI:" manager.kpi ",产品数量:" manager.getProducts()); } }
6.具体访问者:CTOVisitor
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()); } }
6.测试
public class Test { public static void main(String[] args) { BusinessReport report = new BusinessReport(); System.out.println("==========CEO看报表==============="); report.showReport(new CEOVisitor()); System.out.println("==========CTO看报表==============="); report.showReport(new CTOVisitor()); } }
访问者模式应用
- 对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
mikechen睿哥
mikechen睿哥,十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》