「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
定义
是一种行为设计模式,它能将算法与其所作用的对象隔离开来,即将数据结构与数据操作分离,将操作解耦。
理解与举例
个人理解就是,想要让不同的实体根据行为模式访问不同的对象,以下举例
- 比如家长和校长是访问者,而老师和学生是被访问者。
- 家长关心的是老师的教学质量和学生的成绩(仅是举例)
- 校长关心的是老师的薪资和学生的健康(仅是举例)
- 校长和家长看待多个同样对象,但是所观察的视角是不一样的,可以用访问者模式
核心实现
在被访问的类里面加一个对外提供接待访问者的接口。
优缺点
优点
- 开闭原则
- 单一职责原则
- 灵活性
- 扩展性
缺点
- 每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者
- 在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限。
代码实践
以下代码实现以最开头的举例来做,实现校长和家长访问访问多个同样对象,但是访问方式不一样
被访问对象
/**
* 被访问者基类
* @author 勤任风
* @date 2022-01-24 18:10
*/
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public abstract class Person {
public String name;
/**
* 核心接受访问方法
* @param visitor
* @return
**/
public abstract void accept(Visitor visitor);
}
/**
* 教师
* @author 勤任风
* @date 2022-01-24 18:10
*/
@Data
public class Teacher extends Person {
public Teacher(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
/**
* 学生
* @author 勤任风
* @date 2022-01-24 18:14
*/
@Data
public class Student extends Person {
public Student(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
访问者
访问者接口
public interface Visitor {
void visit(Student student);
void visit(Teacher teacher);
}
/**
* 校长类
* @author 勤任风
* @date 2022-01-24 18:16
*/
@Slf4j
public class Principal implements Visitor {
@Override
public void visit(Student student) {
log.info("校长 希望看到学生 {}的健康信息",student.getName());
}
@Override
public void visit(Teacher teacher) {
log.info("校长 希望看到教师 {}的薪资水平",teacher.getName());
}
}
/**
* @author 勤任风
* @date 2022-01-24 18:16
* 家长类
*/
@Slf4j
public class Parent implements Visitor {
@Override
public void visit(Student student) {
log.info("家长 希望看到学生 {}的成绩",student.getName());
}
@Override
public void visit(Teacher teacher) {
log.info("家长 希望看到教师 {}的教学质量",teacher.getName());
}
}
数据报表展示
public class Report {
private List<Person> persons = new LinkedList<>();
public Report(){
persons.add(new Student("张三"));
persons.add(new Student("李四"));
persons.add(new Teacher("王五"));
persons.add(new Teacher("赵六"));
}
//展示
public void show(Visitor visitor){
for(Person person:persons){
person.accept(visitor);
}
}
}
测试
public class VisitorTest {
public static void main(String[] args){
Report report = new Report();
log.info("*******家长看*******");
report.show(new Parent());
log.info("*******校长看*******");
report.show(new Principal());
}
}