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

介绍

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

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

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

基础代码

test类
java 复制代码
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类
java 复制代码
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类
java 复制代码
package Stragy;

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

}
Teacher类
java 复制代码
package Stragy;

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

public abstract class Visitor {
    public abstract void visit(Employee e);
}
IncomeVisitor类
java 复制代码
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类
java 复制代码
package Stragy;

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

策略模式

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

java 复制代码
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抽象方法

java 复制代码
public abstract void accept(Visitor visitor);

在Engineer类中重写

java 复制代码
@Override
    public void accept(Visitor visitor) {
        visitor.EngineerVisit(this);
    }

在Teacher类中重写

java 复制代码
@Override
    public void accept(Visitor visitor) {
        visitor.TeacherVisit(this);
    }

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

java 复制代码
package visitor;

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

在VacationDaysVisitor中重写

java 复制代码
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中重写

java 复制代码
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);
    }
}

测试类中修改调用方式

java 复制代码
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);
        }
    }
}

在测试类中

java 复制代码
for(Employee e : employeeList){
            e.accept(visitor);
            e.accept(vacationDaysVisitor);
        }

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

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

如有错误,敬请指正

相关推荐
晨米酱1 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机6 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机7 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机7 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机7 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤8 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式