设计模式-访问者设计模式
介绍
访问者模式(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);
}
运行结果如下
如有错误,敬请指正