通过一个例子来引入访问者模式。
在医生开具处方单(药单)后,划价人员拿到处方单之后根据药品名称和数量计算总价,而药房工作人员根据药品名称和数量在不药品。
在这里,处方单看出一个药品信息的集合,里面包含了一种或多种不同类型的药品信息,不同类型的工作人员在操作同一个药品信息集合时将提供不同的处理方式,而且还可能会增加新类型的工作人员来操作处方单。
类似这种常见,可以使用访问者模式。
定义:
访问者模式:表示一个作用于某对象结构中的各个元素的操作。访问者模式让用户可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式的结构较为复杂,包含以下5个角色:
下面通过一个案例来进一步学习访问者模式。
//抽象访问者
/**
* 奖励类
* 抽象访问者类
*/
public abstract class Award {
public abstract void visit(Student candidate);
public abstract void visit(Teacher candidate);
}
//具体访问者
/**
* 科研奖
* 具体访问者
*/
public class ScientificAward extends Award {
@Override
public void visit(Student candidate) {
if (candidate.getThesisNumber() > 2) {
System.out.println("学生候选人:" + candidate.getName() + ",论文数"
+ candidate.getThesisNumber() + ",符合评审科研奖的要求");
}
}
@Override
public void visit(Teacher candidate) {
if (candidate.getThesisNumber() > 10) {
System.out.println("教师候选人:" + candidate.getName() + ",论文数"
+ candidate.getThesisNumber() + ",符合评审科研奖的要求");
}
}
}
/**
* 成绩优秀奖
* 具体访问者
*/
public class AchievementAward extends Award {
@Override
public void visit(Student candidate) {
if (candidate.getScore() >= 90) {
System.out.println("学生候选人:" + candidate.getName() + ",平均成绩"
+ candidate.getScore() + ",符合评审成绩优秀奖的要求");
}
}
@Override
public void visit(Teacher candidate) {
if (candidate.getScore() >= 90) {
System.out.println("教师候选人:" + candidate.getName() + ",教学反馈分"
+ candidate.getScore() + ",符合评审成绩优秀奖的要求");
}
}
}
//抽象元素
/**
* 候选人
* 抽象元素类
*/
public interface Candidate {
void accept(Award handle);//接受一个抽象访问者访问
}
//具体元素
/**
* 学生
* 具体元素类
*/
public class Student implements Candidate{
//姓名
private String name;
//成绩分数
private Double score;
//论文数量
private Integer thesisNumber;
public Student(String name, Double score, Integer thesisNumber) {
this.name = name;
this.score = score;
this.thesisNumber = thesisNumber;
}
@Override
public void accept(Award handle) {
handle.visit(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public Integer getThesisNumber() {
return thesisNumber;
}
public void setThesisNumber(Integer thesisNumber) {
this.thesisNumber = thesisNumber;
}
}
/**
* 教师
* 具体元素类
*/
public class Teacher implements Candidate{
//姓名
private String name;
//成绩分数
private Double score;
//论文数量
private Integer thesisNumber;
public Teacher(String name, Double score, Integer thesisNumber) {
this.name = name;
this.score = score;
this.thesisNumber = thesisNumber;
}
@Override
public void accept(Award handle) {
handle.visit(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public Integer getThesisNumber() {
return thesisNumber;
}
public void setThesisNumber(Integer thesisNumber) {
this.thesisNumber = thesisNumber;
}
}
//对象结构
/**
* 候选人列表类
* 充当对象结构
*
*/
public class CandidateList {
private List list = new ArrayList<>();
public void addCandidate(Candidate candidate) {
list.add(candidate);
}
//遍历访问候选人集合中的每一个对象
public void accept(Award handler) {
for (Candidate c : list) {
c.accept(handler);
}
}
}
//客户端
public class Client {
public static void main(String[] args) {
/**
* 案例需求描述:
* 某公司为某高校开发一套奖励审批系统,该系统可以实现教师奖励和学生奖励的审批,
* 如果教师发表论文数操作10篇或者学生论文数超过两篇可以平科研奖;
* 如果教师教学反馈分大于等于90分或者学生平均成绩大于等于90分可以评选成绩优秀奖。
* 请用访问者模式实现该系统,以判断候选人集合中的教师或学生是否符合某种获奖要求。
*
*/
//定义候选人集合
CandidateList candidateList = new CandidateList();
Candidate s1,s2,s3,t1,t2,t3;
s1 = new Student("刘备",70.0,1);
s2 = new Student("张飞",78.0,3);
s3 = new Student("关羽",91.5,0);
t1 = new Teacher("诸葛亮",95.0,0);
t2 = new Teacher("庞统",75.0,11);
t3 = new Teacher("周瑜",88.5,6);
candidateList.addCandidate(s1);
candidateList.addCandidate(s2);
candidateList.addCandidate(s3);
candidateList.addCandidate(t1);
candidateList.addCandidate(t2);
candidateList.addCandidate(t3);
//以科研奖来访问
Award scientificAward = new ScientificAward();
candidateList.accept(scientificAward);
System.out.println("-----------------------");
//以成绩优秀奖来访问
Award achievementAward = new AchievementAward();
candidateList.accept(achievementAward);
}
}
【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。
【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git