访问者模式详解(定义角色及应用实例)

访问者模式详解(定义角色及应用实例)-mikechen

访问者模式定义

访问者模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,在不改变数据结构的前提下定义一些新的操作。

访问者模式将对数据的操作,与数据结构进行分离,是行为类模式中最复杂的一种模式。

 

访问者模式作用

访问者模式作用:简单来说访问者模式主要的作用就是将“数据结构”和“数据操作”进行分离,解决这两者之间耦合性的问题。

 

访问者模式角色

访问者模式实现的关键:是如何将作用于元素的操作分离出来封装成独立的类。

访问者模式的基本结构,包含以下主要角色,如下图所示:

访问者模式详解(定义角色及应用实例)-mikechen

1. Vistor(抽象访问者)

定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素,就好像是王者荣耀里面不同的玩家。

 

2. ConcreteVisitor(具体访问者)

每个具体访问者都实现了Vistor中定义的操作,就好比是具体某一个玩家。

 

3. Element(抽象元素)

声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数,可以类比成王者里面英雄的模板。

 

4.ConcreteElement(具体元素)

实现了Element中的accept()方法,调用Vistor的访问方法以便完成对一个元素的操作,可以表示为具体某一个英雄,好比是庄周和甄姬。

 

5. ObjectStructure(对象结构)

可以是组合模式,也可以是集合,是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。

访问者模式类图如下:

访问者模式详解(定义角色及应用实例)-mikechen

 

访问者模式案例

访问者模式的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,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法