常用的设计模式之访问者模式

访问者模式(Visitor Pattern) 是一种将数据结构与数据操作分离的设计模式。是指封装一

些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些

元素的新的操作。属于行为型模式。

原文:Represent an operation to be performed on the elements of an object structure.Visitor lets you define a new operation without changing the classes of the elements on which it operates...o

访问者模式被称为最复杂的设计模式,并且使用频率不高,设计模式的作者也评价为:大多

情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就真的需要使用了。访问者模

式的基本思想是, 针对系统中拥有固定类型数的对象结构(元素) , 在其内提供一个accept()

方法用来接受访问者对象的访问。不同的访问者对同一元素的访问内容不同,使得相同的元素

集合可以产生不同的数据结果。accept() 方法可以接收不同的访问者对象, 然后在内部将自己(元

素) 转发到接收到的访问者对象的visit() 方法内。访问者内部对应类型的visit() 方法就会得到回

调执行, 对元素进行操作。也就是通过两次动态分发(第一次是对访问者的分发accept() 方法,

第二次是对元素的分发visit() 方法) , 才最终将一个具体的元素传递到一个具体的访问者。如此

一来,就解耦了数据结构与操作,且数据操作不会改变元素状态。

访问者模式的核心是,解耦数据结构与数据操作,使得对元素的操作具备优秀的扩展性。可

以通过扩展不同的数据操作类型(访问者)实现对相同元素集的不同的操作。

解耦数据结构和数据操作,

类比

食堂里的座位,吃放工具,窗口(数据结构固定的), 进来吃饭的人就是访问者他们来操作上面的数 据是不固定的,

kpi考核 其组织方式是固定的(),查看kpi的人和被考查的人的方式是不固定的

类图:

在这里插入图片描述

代码:

访问者接口

public interface IVisitor {

    void visit(Engineer engineer);

    void visit(Manager manager);

}

被考核者的抽象类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(IVisitor visitor);
}

被考核者角色普通工程师Engineer

public class Engineer extends Employee {
    public Engineer(String name) {
        super(name);
    }

    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }

    //考核指标是每年的代码量
    public int getCodeLines(){
        return new Random().nextInt(10* 10000);
    }
}

被考核者角色产品经理Manager

public class Manager extends Employee {
    public Manager(String name) {
        super(name);
    }

    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }

    //考核的是每年新产品研发数量
    public int getProducts(){
        return new Random().nextInt(10);
    }
}

查看考核成绩的角色CEOVistitor

public class CEOVistitor implements IVisitor {
    public void visit(Engineer engineer) {
        System.out.println("工程师" +  engineer.name + ",KIP:" + engineer.kpi);
    }

    public void visit(Manager manager) {
        System.out.println("经理:" +  manager.name + ",KPI:" + manager.kpi + ",产品数量:" + manager.getProducts());
    }
}

查看考核成绩的角色CTOVistitor

public class CTOVistitor implements IVisitor {
    public void visit(Engineer engineer) {
        System.out.println("工程师" +  engineer.name + ",代码行数:" + engineer.getCodeLines());
    }

    public void visit(Manager manager) {
        System.out.println("经理:" +  manager.name + ",产品数量:" + manager.getProducts());
    }
}

报表的方法BusinessReport

public class BusinessReport {
    private List<Employee> employees = new LinkedList<Employee>();

    public BusinessReport() {
        employees.add(new Manager("产品经理A"));
        employees.add(new Engineer("程序员A"));
        employees.add(new Engineer("程序员B"));
        employees.add(new Engineer("程序员C"));
        employees.add(new Manager("产品经理B"));
        employees.add(new Engineer("程序员D"));
    }

    public void showReport(IVisitor visitor){
        for (Employee employee : employees) {
            employee.accept(visitor);
        }
    }
}

测试方法:

public class Test {
    public static void main(String[] args) {
        BusinessReport report = new BusinessReport();
        System.out.println("==========CEO看报表===============");
        report.showReport(new CEOVistitor());
        System.out.println("==========CTO看报表===============");
        report.showReport(new CTOVistitor());
    }
}

测试结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱童鞋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值