当前位置: 首页 > article >正文

设计模式-访问者设计模式

介绍

访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变个元素的类的前提下定义作用于这些元素的新操作。

问题:在一个机构里面有两种员工,1.Teacher   2.Engineer   员工有name, income, vacationDays三种属性,想要对不同的员工有不同的算法实现更新income和vacationDays的操作。

首先引导出策略模式,对员工实现不同的算法策略实现更新操作。

基础代码

test类
package Stragy;

import java.util.ArrayList;
import java.util.List;

public class test {
    public static void main(String[] args) {
        Employee e1 = new Teacher("张三", 8000, 10);
        Employee e2 = new Engineer("李四", 7000, 20);

        Visitor visitor = new IncomeVisitor();

        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(e1);
        employeeList.add(e2);

        for(Employee e : employeeList){
            visitor.visit(e);
        }

        for(Employee e : employeeList){
            System.out.println(e);
        }
    }
}
 Employee类
package Stragy;

public abstract class Employee {
    private String name;
    private double income;
    private int vacationDays;

    public Employee(String name, double income, int vacationDays) {
        this.name = name;
        this.income = income;
        this.vacationDays = vacationDays;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getIncome() {
        return income;
    }

    public void setIncome(double income) {
        this.income = income;
    }

    public int getVacationDays() {
        return vacationDays;
    }

    public void setVacationDays(int vacationDays) {
        this.vacationDays = vacationDays;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", income=" + income +
                ", vacationDays=" + vacationDays +
                '}';
    }
}
Engineer类
package Stragy;

public class Engineer extends Employee{
    public Engineer(String name, double income, int vacationDays) {
        super(name, income, vacationDays);
    }

}
 Teacher类
package Stragy;

public class Teacher extends Employee {
    public Teacher(String name, double income, int vacationDays) {
        super(name, income, vacationDays);
    }
}
Visitor类 
package Stragy;

public abstract class Visitor {
    public abstract void visit(Employee e);
}
IncomeVisitor类
package Stragy;

public class IncomeVisitor extends Visitor{
    @Override
    public void visit(Employee e) {
        if(e instanceof Teacher){
            e.setIncome(e.getIncome() + 500);
        }
        if(e instanceof Engineer){
            e.setIncome(e.getIncome() + 800);
        }

    }
}
 VacationDaysVisitor类
package Stragy;

public class VacationDayVisitor extends Visitor{
    @Override
    public void visit(Employee e) {
        e.setVacationDays(e.getVacationDays() + 8);
    }
}

策略模式

基础代码就是按照策略模式实现的,但是在不同的员工对算法的不同选择上尚可优化,在策略模式中,是通过 if 语句判断算法的不同选择。

package Stragy;

public class IncomeVisitor extends Visitor{
    @Override
    public void visit(Employee e) {
        if(e instanceof Teacher){
            e.setIncome(e.getIncome() + 500);
        }
        if(e instanceof Engineer){
            e.setIncome(e.getIncome() + 800);
        }

    }
}

在IncomeVisitor类中,通过instanceof判断当前员工是哪种类型来选择实现哪种算法,使用访问者的双分派方式可以省去 if 语句,也就是使用两次动态绑定。 

访问者模式

在访问者模式中,修改了以下内容:

在Employee类中添加accept抽象方法

public abstract void accept(Visitor visitor);

 在Engineer类中重写

@Override
    public void accept(Visitor visitor) {
        visitor.EngineerVisit(this);
    }

在Teacher类中重写

@Override
    public void accept(Visitor visitor) {
        visitor.TeacherVisit(this);
    }

在Visitor类中不再使用visit方法,替换为不同员工的算法选择,在此处,我的理解是用两个不同的方法代替了 if 语句。

package visitor;

public abstract class Visitor {
    public abstract void TeacherVisit(Employee e);
    public abstract void EngineerVisit(Employee e);
}

在VacationDaysVisitor中重写

package visitor;

public class VacationDaysVisitor extends Visitor{
    @Override
    public void TeacherVisit(Employee e) {
        e.setVacationDays(e.getVacationDays() + 5);
    }

    @Override
    public void EngineerVisit(Employee e) {
        e.setVacationDays(e.getVacationDays() + 8);
    }
}

在IncomeVisitor中重写

package visitor;

public class IncomeVisitor extends Visitor{
    @Override
    public void TeacherVisit(Employee e) {
        e.setIncome(e.getIncome() + 500);
    }

    @Override
    public void EngineerVisit(Employee e) {
        e.setIncome(e.getIncome() + 800);
    }
}

测试类中修改调用方式

package visitor;

import java.util.ArrayList;
import java.util.List;

public class test {
    public static void main(String[] args) {
        Employee e1 = new Teacher("张三", 8000, 10);
        Employee e2 = new Engineer("李四", 7000, 20);

        Visitor visitor = new IncomeVisitor();
        VacationDaysVisitor vacationDaysVisitor = new VacationDaysVisitor();

        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(e1);
        employeeList.add(e2);

        for(Employee e : employeeList){
            e.accept(visitor);
            e.accept(vacationDaysVisitor);
        }

        for(Employee e : employeeList){
            System.out.println(e);
        }
    }
}

在测试类中 

for(Employee e : employeeList){
            e.accept(visitor);
            e.accept(vacationDaysVisitor);
        }

此处调用accept方法进行更新的时候,使用到双分派的技术在选择 e 员工的时候用到一次动态绑定,绑定到真实的员工,在 Engineer和Teacher中选择 visitor 算法的时候再次用到动态绑定,绑定到真实的IncomeVisitor或VacationDaysVisitor,通过两次绑定,即可为合适的员工选择合适的算法。

@Override
    public void accept(Visitor visitor) {
        visitor.EngineerVisit(this);
    }
运行结果如下

如有错误,敬请指正


http://www.kler.cn/a/450027.html

相关文章:

  • 《Vue3实战教程》5:响应式基础
  • java Redis 操作工具类封装(备忘)
  • 怎么设置电脑密码?Windows和Mac设置密码的方法
  • 0.96寸OLED显示屏详解
  • Zabbix6.0升级为7.2
  • ARM异常处理 M33
  • linux Sudo权限
  • 《探秘 Qt Creator Manual 4.11.1》
  • 基于Java的秦皇岛旅游景点管理系统
  • 【WRF教程第3.5期】预处理系统 WPS 详解:以4.5版本为例
  • 电脑出现 0x0000007f 蓝屏问题怎么办,参考以下方法尝试解决
  • 1.使用 Couchbase 数仓和 Temporal(一个分布式任务调度和编排框架)实现每 5 分钟的增量任务
  • Vue(四)
  • Playwright 解决京东滑块:自动化挑战大揭秘
  • MLU运行Stable Diffusion WebUI Forge【flux】
  • springBoot Bean加载流程
  • k8s总结
  • 汉塔科技-上网行为管理系统 ping.php 远程命令执行漏洞复现
  • 梳理你的思路(从OOP到架构设计)_设计模式Observer模式
  • OPPO Android面试题及参考答案 (上)
  • 006_ipc概述及共享内存
  • Linux 下SVN新手操作手册
  • 解析mysqlbinlog
  • Word使用分隔符实现页面部分分栏
  • Kotlin - 协程结构化并发Structured Concurrency
  • CSS|13 position属性