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

介绍

访问者模式(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);
    }
运行结果如下

如有错误,敬请指正

相关推荐
夏旭泽3 小时前
设计模式-中介模式
设计模式
澄澈i3 小时前
设计模式学习[13]---抽象工厂模式+简单工厂+工厂方法模式回顾
学习·设计模式·抽象工厂模式
越甲八千4 小时前
重拾设计模式--原型模式
设计模式·原型模式
小白64024 小时前
浅谈目前我开发的前端项目用到的设计模式
前端·设计模式·状态模式
线程A10 小时前
设计模式之 abstract factory
java·开发语言·设计模式
Front思10 小时前
12种Vue设计模式
javascript·vue.js·设计模式
夏旭泽1 天前
设计模式-迭代器模式
设计模式·迭代器模式
抓哇FullStack-Junior1 天前
设计模式——建造者模式
java·开发语言·设计模式·建造者模式
shinelord明1 天前
【再谈设计模式】外观模式~复杂系统交互的简化大师
开发语言·数据结构·设计模式·软件工程