上一篇:设计模式(二十)——模板模式
下一篇:设计模式(二十二)——一文搞懂中介者模式与观察者模式区别
一、概述
官方解释: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.(封装一些作用于某种数据结构中的各种元素,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。)
我的理解:
1、基本结构:访问者类(Visitor类或ConcreteVisitor类)提供访问方法,元素类(Element类或ConcreteElement类)提供元素的属性和相关方法,对象结构类(ObjectStructure类)中提供对元素类的统一管理。
2、关于注入引用的问题:一般来说,可以使用属性注入类的方式,也可以使用形参注入函数的方式。
3、最后的操作,客户端既访问元素类(Element类或ConcreteElement类)、又访问访问者类(Visitor类或ConcreteVisitor类),如果没有特殊业务需求,一般来说,访问者类ConcreteElement可以访问各个具体元素类ConcreteElement,最后得到的结果是各个具体访问者ConcreteVisitor和各个具体元素ConcreteElement的笛卡儿积,数量是(ConcreteVisitor个数*ConcreteElement个数)。(特殊业务需求是指某个具体访问者ConcreteVisitor因为业务需求只需访问指定的ConcreteElement,或者某个ConcreteElement只需被特定的访问者访问,其他访问没有业务意义或业务权限上不允许)
参与者(5个):访问者(包括抽象访问者AbstractVisitor和具体访问者ConcreteVisitor)、元素(包括抽象运算Element和具体元素ConcreteElement)、对象结构ObjectStructure
类图:
二、代码
代码1——单纯的访问者模式 代码2——访问者模式OA系统
代码1——单纯的访问者模式
package mypackage;
import java.util.ArrayList;
public class DesignPatternDemo {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
Element element = new ConcreteElementA();
Element element2 = new ConcreteElementB();
objectStructure.addElement(element);
objectStructure.addElement(element2);
Visitor visitor = new ConcreteVisitorA();
objectStructure.accept(visitor);
visitor = new ConcreteVisitorB();
objectStructure.accept(visitor);
}
}
abstract class Visitor { // 访问者类 提供访问方法
public abstract void visit(ConcreteElementA cElementA);
public abstract void visit(ConcreteElementB cElementB);
}
interface Element { // 被访问元素
public void accept(Visitor visitor);
}
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operation() {
System.out.println("This is the ConcreteElementA");
}
}
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operation() {
System.out.println("This is the ConcreteElementB");
}
}
class ConcreteVisitorA extends Visitor {
@Override
public void visit(ConcreteElementA cElementA) {
System.out.print("This is in ConcreteVisitorA ");
cElementA.operation();
}
@Override
public void visit(ConcreteElementB cElementB) {
System.out.print("This is in ConcreteVisitorA ");
cElementB.operation();
}
}
class ConcreteVisitorB extends Visitor {
@Override
public void visit(ConcreteElementA cElementA) {
System.out.print("This is in ConcreteVisitorB ");
cElementA.operation();
}
@Override
public void visit(ConcreteElementB cElementB) {
System.out.print("This is in ConcreteVisitorB ");
cElementB.operation();
}
}
class ObjectStructure {// 管理访问者
private ArrayList<Element> list = new ArrayList<>();
public void accept(Visitor visitor) {
for (Element element : list) {
element.accept(visitor);
}
}
public void addElement(Element element) {
list.add(element);
}
public void removeElement(Element element) {
list.remove(element);
}
}
输出1:
This is in ConcreteVisitorA This is the ConcreteElementA
This is in ConcreteVisitorA This is the ConcreteElementB
This is in ConcreteVisitorB This is the ConcreteElementA
This is in ConcreteVisitorB This is the ConcreteElementB
小结1:这里两个具体访问者ConcreteVisitorA和ConcreteVisitorB,各新建一个具体访问者对象,两个具体元素ConcreteElementA和ConcreteElementB,各新建一个具体元素对象,所以最后四个访问结果。
代码2——访问者模式OA系统
package mypackage;
import java.util.ArrayList;
public class DesignPatternDemo {
public static void main(String[] args) {
EmployeeList list = new EmployeeList();
Employee fulltimeEmployee1 = new FulltimeEmployee("张三", 3200, 45);
Employee fulltimeEmployee2 = new FulltimeEmployee("李四", 2000, 40);
Employee fulltimeEmployee3 = new FulltimeEmployee("王五", 2400, 38);
Employee parttimeEmployee1 = new ParttimeEmployee("刘六", 80, 20);
Employee parttimeEmployee2 = new ParttimeEmployee("赵七", 60, 18);
list.addElement(fulltimeEmployee1);
list.addElement(fulltimeEmployee2);
list.addElement(fulltimeEmployee3);
list.addElement(parttimeEmployee1);
list.addElement(parttimeEmployee2);
Department department = new FADepartment();
list.accept(department);
System.out.println();
department = new HRDepartment();
list.accept(department);
}
}
interface Employee {
public void accept(Department department);
}
class FulltimeEmployee implements Employee {
private String name;
private double weeklyWage;
private int workTime;
public FulltimeEmployee(String name, double weeklyWage, int workTime) {
super();
this.name = name;
this.weeklyWage = weeklyWage;
this.workTime = workTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeeklyWage() {
return weeklyWage;
}
public void setWeeklyWage(double weeklyWage) {
this.weeklyWage = weeklyWage;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
@Override
public void accept(Department department) {
department.visit(this);
}
}
class ParttimeEmployee implements Employee {
private String name;
private double hourWage;
private int workTime;
public ParttimeEmployee(String name, double hourWage, int workTime) {
super();
this.name = name;
this.hourWage = hourWage;
this.workTime = workTime;
}
public double getHourWage() {
return hourWage;
}
public void setHourWage(double hourWage) {
this.hourWage = hourWage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
@Override
public void accept(Department department) {
department.visit(this);
}
}
abstract class Department {
public abstract void visit(FulltimeEmployee employee);
public abstract void visit(ParttimeEmployee employee);
}
class FADepartment extends Department {
// 公司财务部门 访问全职员工 访问函数中计算出该全职员工 本月工资
@Override
public void visit(FulltimeEmployee employee) {
int workTime = employee.getWorkTime();
double weeklyWage = employee.getWeeklyWage();
if (workTime > 40) {
weeklyWage = weeklyWage + (workTime - 40) * 100; // 每月加班费 100元/小时
} else if (workTime < 40) {
weeklyWage = weeklyWage - (40 - workTime) * 80; // 每个月 迟到 不能正常上班 扣除
// 80元/小时
if (weeklyWage < 0) {
weeklyWage = 0; // 工资最少为0 不能变成负数
}
}
System.out.println("全职员工: " + employee.getName() + "本月实际工资为: " + weeklyWage);
}
// 公司财务部门 访问兼职员工 访问函数中计算出该兼职员工 本月工资
@Override
public void visit(ParttimeEmployee employee) {
int workTime = employee.getWorkTime();
double hourWage = employee.getHourWage();
System.out.println("兼职员工: " + employee.getName() + "本月实际工资为: " + workTime * hourWage);
}
}
class HRDepartment extends Department {
// 公司人事部门 访问全职员工 访问函数中计算出该全职员工 本月加班时间或旷缺时间
@Override
public void visit(FulltimeEmployee employee) { // 这里简单处理
// 每周只要40小时即可,加班和旷缺可以相互累计
int workTime = employee.getWorkTime();
System.out.print("正式员工: " + employee.getName() + " ,本月实际工作时间: " + employee.getWorkTime() + " 小时 ");
if (workTime > 40) {
System.out.print("正式员工: " + employee.getName() + " ,本月加班时间: " + (workTime - 40) + " 小时");
} else if (workTime < 40) {
System.out.print("正式员工: " + employee.getName() + " ,本月旷缺时间: " + (40 - workTime) + " 小时");
}
System.out.println();
}
@Override
public void visit(ParttimeEmployee employee) {
int workTime = employee.getWorkTime();
System.out.println("兼职员工: " + employee.getName() + " ,本月实际工作时间: " + employee.getWorkTime() + " 小时");
}
}
class EmployeeList {
private ArrayList<Employee> list = new ArrayList<>();
public void addElement(Employee employee) {
list.add(employee);
}
public void accept(Department department) {
for (Employee employee : list) {
employee.accept(department);
}
}
}
输出2:
全职员工: 张三本月实际工资为: 3700.0
全职员工: 李四本月实际工资为: 2000.0
全职员工: 王五本月实际工资为: 2240.0
兼职员工: 刘六本月实际工资为: 1600.0
兼职员工: 赵七本月实际工资为: 1080.0
正式员工: 张三 ,本月实际工作时间: 45 小时 正式员工: 张三 ,本月加班时间: 5 小时
正式员工: 李四 ,本月实际工作时间: 40 小时
正式员工: 王五 ,本月实际工作时间: 38 小时 正式员工: 王五 ,本月旷缺时间: 2 小时
兼职员工: 刘六 ,本月实际工作时间: 20 小时
兼职员工: 赵七 ,本月实际工作时间: 18 小时
小结2:这里新建5个被元素对象,2个访问者对象,所以最后10条访问结果。
三、小结
访问者模式,结合了官方解释的简单理解,提供一个作用于某对象结构(指ObjectStructure类)中的各元素(指Element和ConcreteElement类)的操作表示(指Visitor类),它使我们可以在不改变各元素的类(指ConcreteElement类)的前提下定义作用于这些元素的新操作(指ConcreteVisitor类)。
上一篇:设计模式(二十)——模板模式