访问者模式
定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
访问者模式角色介绍
- Visitor:抽象访问者,定义访问者公共接口。
- ConcreteVisitor:具体访问者,实现Visitor类,以不同的角度访问元素。
- Element:抽象元素,定义元素公共接口。
- ConcreteElement:具体元素,实现Element类,并且接收Visitor访问元素。
- ObjectStructure:对象结构,存放具体元素集合。
访问者模式属于行为型模式,是设计模式中最难理解的模式。从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法。每个人看待事情都不一样,以学生成绩来说,体育老师更关心学生的体育成绩,而班主任关心学生的理论成绩,这时访问者模式派上用场了。
代码示例
抽象访问者
public interface Visitor {
void visit(Student student);//统一访问学生
}
抽象学生类
public interface Student {
void accept(Visitor visitor);//接收访问者方法
void showSportsScore();//显示学生体育成绩
void showTheoryScore();//显示学生理论成绩
}
具体访问者类(班主任、体育老师)
public class HeadTeacher implements Visitor{
public void visit(Student student) {
student.showTheoryScore();//班主任只关心学生的理论成绩
}
}
public class GymTeacher implements Visitor{
public void visit(Student student) {
student.showSportsScore();//体育老师只关心学生的体育成绩
}
}
具体学生类(小明、小红)
public class Xiaoming implements Student{
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void showSportsScore(){
System.out.println("显示小明体育成绩");
}
public void showTheoryScore(){
System.out.println("显示小明理论成绩");
}
}
public class Xiaohong implements Student{
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void showSportsScore(){
System.out.println("显示小红体育成绩");
}
public void showTheoryScore(){
System.out.println("显示小红理论成绩");
}
}
成绩集合
public class ScoreManager {
private List<Student> students = new ArrayList<Student>();
public ScoreManager() {
students.add(new Xiaohong());
students.add(new Xiaoming());
}
public List<Student> getStudents() {
return students;
}
}
客户端
List<Student> students = new ScoreManager().getStudents();
// 班主任访问学生成绩
for (Student s : students) {
s.accept(new HeadTeacher());
}
// 体育老师访问学生成绩
for (Student s : students) {
s.accept(new GymTeacher());
}
有人会问,怎么跟UML图不一样啊。是的,我为了通用性,我把该实现的方法都提炼到父类,这样Visitor不用具体对应哪个元素类方法。上面的例子很明白看出其实就是每个访问者所关心的地方不一样。访问者模式带来的好处很明显,扩展性强。正如《设计模式》的作者GoF对访问者模式的描述:大多数情况下,你并需要使用访问者模式,但是当你一旦需要使用它时,那你就是真的需要它了。不足之处望指教。