访问者模式Visitor
例题:
- 校长和院长检查教师和学生
- 校长和院长检查教师的工作情况和学生的学习情况
- 校长关注教师的教学工作量,学生学习的课程
- 院长关注教师的课程,学生的学习成绩
- 由于校长和院长对于教师和学生的关注点是不一样的,这就需要对教师和学生进行不同的处理
- 教师的工作和学生的学习相对稳定,访问者和处理方式多种多样。
import java.util.ArrayList;
import java.util.List;
//创建一个人员基类
abstract class Person{
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//教师
class Teacher extends Person{
private String course;//所教课程
private int amount;//学时
public Teacher(String name, String course, int amount) {
super(name);
this.course = course;
this.amount = amount;
}
public String getCourse() {
return course;
}
public int getAmount() {
return amount;
}
}
//学生
class Student extends Person{
private String course;//所学课程
private int grade;//成绩
public Student(String name, String course, int grade) {
super(name);
this.course = course;
this.grade = grade;
}
public String getCourse() {
return course;
}
public int getGrade() {
return grade;
}
}
class PresidentVisitor{//校长访问
public void visit(Person person) {
if(person instanceof Teacher) {
Teacher teacher=(Teacher)person;
System.out.println("校长 访问老师 "+teacher.getName()+"学时:"+teacher.getAmount());
}else if(person instanceof Student) {
Student student=(Student)person;
System.out.println("校长 访问学生 "+student.getName()+"课程:"+student.getCourse());
}
}
}
class DeanVisitor{//院长访问
public void visit(Person person) {
if(person instanceof Teacher) {
Teacher teacher=(Teacher)person;
System.out.println("院长 访问老师 "+teacher.getName()+"课程:"+teacher.getCourse());
}else if(person instanceof Student) {
Student student=(Student)person;
System.out.println("院长 访问学生 "+student.getName()+"成绩:"+student.getGrade());
}
}
}
public class Main{
public static void main(String[] args){
List<Person>listperson=new ArrayList<Person>();
Person t1=new Teacher("张老师","编译原理",48);//创建老师
Person t2=new Teacher("王老师","数据库",54);
Student s1=new Student("赵同学","编译原理",90);//创建学生
Student s2=new Student("刘同学","数据库",82);
listperson.add(t1);listperson.add(t2);
listperson.add(s1);listperson.add(s2);
PresidentVisitor pv=new PresidentVisitor();//创建校长
for(Person b:listperson) {
pv.visit(b);
}
DeanVisitor dv=new DeanVisitor();//创建院长
for(Person b:listperson) {
dv.visit(b);
}
}
}
改进:发现类PresidentVisitor和DeanVisitor有相同的方法visit,就可以提出一个接口Visitor,它含有抽象方法visit(),类PresidentVisitor和DeanVisitor实现它并实现其中的visit方法。
import java.util.ArrayList;
import java.util.List;
//创建一个人员基类
abstract class Person{
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//教师
class Teacher extends Person{
private String course;//所教课程
private int amount;//学时
public Teacher(String name, String course, int amount) {
super(name);
this.course = course;
this.amount = amount;
}
public String getCourse() {
return course;
}
public int getAmount() {
return amount;
}
}
//学生
class Student extends Person{
private String course;//所学课程
private int grade;//成绩
public Student(String name, String course, int grade) {
super(name);
this.course = course;
this.grade = grade;
}
public String getCourse() {
return course;
}
public int getGrade() {
return grade;
}
}
interface Visitor{
abstract void visit(Person person);
}
class PresidentVisitor implements Visitor{//校长访问
public void visit(Person person) {
if(person instanceof Teacher) {
Teacher teacher=(Teacher)person;
System.out.println("校长 访问老师 "+teacher.getName()+"学时:"+teacher.getAmount());
}else if(person instanceof Student) {
Student student=(Student)person;
System.out.println("校长 访问学生 "+student.getName()+"课程:"+student.getCourse());
}
}
}
class DeanVisitor implements Visitor{//院长访问
public void visit(Person person) {
if(person instanceof Teacher) {
Teacher teacher=(Teacher)person;
System.out.println("院长 访问老师 "+teacher.getName()+"课程:"+teacher.getCourse());
}else if(person instanceof Student) {
Student student=(Student)person;
System.out.println("院长 访问学生 "+student.getName()+"成绩:"+student.getGrade());
}
}
}
public class Main{
public static void main(String[] args){
List<Person>listperson=new ArrayList<Person>();
Person t1=new Teacher("张老师","编译原理",48);//创建老师
Person t2=new Teacher("王老师","数据库",54);
Student s1=new Student("赵同学","编译原理",90);//创建学生
Student s2=new Student("刘同学","数据库",82);
listperson.add(t1);listperson.add(t2);
listperson.add(s1);listperson.add(s2);
Visitor pv=new PresidentVisitor();//创建校长
for(Person b:listperson) {
pv.visit(b);
}
Visitor dv=new DeanVisitor();//创建院长
for(Person b:listperson) {
dv.visit(b);
}
}
}
再次改进
Visitor中定义visit为重载函数,声明两个visit方法,参数分别是Teacher和Student.
对于Teacher.、Student的访问会调用两个不同的方法,以此达成区别对待、差异化处理。
import java.util.ArrayList;
import java.util.List;
//创建一个人员基类
abstract class Person{
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//教师
class Teacher extends Person{
private String course;//所教课程
private int amount;//学时
public Teacher(String name, String course, int amount) {
super(name);
this.course = course;
this.amount = amount;
}
public String getCourse() {
return course;
}
public int getAmount() {
return amount;
}
}
//学生
class Student extends Person{
private String course;//所学课程
private int grade;//成绩
public Student(String name, String course, int grade) {
super(name);
this.course = course;
this.grade = grade;
}
public String getCourse() {
return course;
}
public int getGrade() {
return grade;
}
}
interface Visitor{
void visit(Teacher teacher);
void visit(Student student);
}
class PresidentVisitor implements Visitor{//校长访问
@Override
public void visit(Teacher teacher) {
// TODO Auto-generated method stub
System.out.println("校长 访问老师 "+teacher.getName()+"学时:"+teacher.getAmount());
}
@Override
public void visit(Student student) {
// TODO Auto-generated method stub
System.out.println("校长 访问学生 "+student.getName()+"课程:"+student.getCourse());
}
}
class DeanVisitor implements Visitor{//院长访问
@Override
public void visit(Teacher teacher) {
// TODO Auto-generated method stub
System.out.println("院长 访问老师 "+teacher.getName()+"课程:"+teacher.getCourse());
}
@Override
public void visit(Student student) {
// TODO Auto-generated method stub
System.out.println("院长 访问学生 "+student.getName()+"成绩:"+student.getGrade());
}
}
public class Main{
public static void main(String[] args){
List<Person>listperson=new ArrayList<Person>();
Person t1=new Teacher("张老师","编译原理",48);//创建老师
Person t2=new Teacher("王老师","数据库",54);
Person s1=new Student("赵同学","编译原理",90);//创建学生
Person s2=new Student("刘同学","数据库",82);
listperson.add(t1);listperson.add(t2);
listperson.add(s1);listperson.add(s2);
Visitor pv=new PresidentVisitor();//创建校长
for(Person b:listperson) {
if(b instanceof Teacher) {
Teacher teacher=(Teacher)b;
pv.visit(teacher);
}else if(b instanceof Student) {
Student student=(Student)b;
pv.visit(student);
}
}
Visitor dv=new DeanVisitor();//创建院长
for(Person b:listperson) {
if(b instanceof Teacher) {
Teacher teacher=(Teacher)b;
dv.visit(teacher);
}else if(b instanceof Student) {
Student student=(Student)b;
dv.visit(student);
}
}
}
}
如果在老师和学生类定义方法accept ( Visitor visitor )接受校长或院长访问,在方法实现时通过:visitor.visit(this),当前老师或学生作为实参传递,就去除了判断
import java.util.ArrayList;
import java.util.List;
//创建一个人员基类
abstract class Person{
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void accept(Visitor visitor);
}
//教师
class Teacher extends Person{
private String course;//所教课程
private int amount;//学时
public Teacher(String name, String course, int amount) {
super(name);
this.course = course;
this.amount = amount;
}
public String getCourse() {
return course;
}
public int getAmount() {
return amount;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
//学生
class Student extends Person{
private String course;//所学课程
private int grade;//成绩
public Student(String name, String course, int grade) {
super(name);
this.course = course;
this.grade = grade;
}
public String getCourse() {
return course;
}
public int getGrade() {
return grade;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
interface Visitor{
void visit(Teacher teacher);
void visit(Student student);
}
class PresidentVisitor implements Visitor{//校长访问
@Override
public void visit(Teacher teacher) {
// TODO Auto-generated method stub
System.out.println("校长 访问老师 "+teacher.getName()+"学时:"+teacher.getAmount());
}
@Override
public void visit(Student student) {
// TODO Auto-generated method stub
System.out.println("校长 访问学生 "+student.getName()+"课程:"+student.getCourse());
}
}
class DeanVisitor implements Visitor{//院长访问
@Override
public void visit(Teacher teacher) {
// TODO Auto-generated method stub
System.out.println("院长 访问老师 "+teacher.getName()+"课程:"+teacher.getCourse());
}
@Override
public void visit(Student student) {
// TODO Auto-generated method stub
System.out.println("院长 访问学生 "+student.getName()+"成绩:"+student.getGrade());
}
}
class ObjectList{
private List<Person>lists=new ArrayList<Person>();
public void Attach(Person element) {//增加
lists.add(element);
}
public void Detach(Person element) {//移除
lists.remove(element);
}
public void Display(Visitor visitor) {//查看显示
for(Person element:lists) {
element.accept(visitor);
}
}
}
public class Main{
public static void main(String[] args){
Person t1=new Teacher("张老师","编译原理",48);//创建老师
Person t2=new Teacher("王老师","数据库",54);
Person s1=new Student("赵同学","编译原理",90);//创建学生
Person s2=new Student("刘同学","数据库",82);
Visitor p=new PresidentVisitor();//创建校长
Visitor d=new DeanVisitor();//院长
ObjectList listperson=new ObjectList();
listperson.Attach(t1);
listperson.Attach(t2);
listperson.Attach(s1);
listperson.Attach(s2);
listperson.Display(p);
System.out.println("================");
listperson.Display(d);
}
}
访问者模式:
- 访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
- 主要将数据结构与数据操作分离,解决数据结构和操作耦合性问题。
- 访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口。
访问者模式的基本结构代码
import java.util.ArrayList;
import java.util.List;
abstract class Element{
public abstract void Accept(Visitor visitor);
}
class ConcreteElementA extends Element{
public void Accept(Visitor visitor) {
visitor.VisitConcreteElementA(this);
}
public void OperationA() {}
}
class ConcreteElementB extends Element{
public void Accept(Visitor visitor) {
visitor.VisitConcreteElementB(this);
}
public void OperationB() {}
}
abstract class Visitor{
public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
}
class ConcreteVisitor1 extends Visitor{
@Override
public void VisitConcreteElementA(ConcreteElementA concreteElementA) {
// TODO Auto-generated method stub
System.out.println(concreteElementA.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
@Override
public void VisitConcreteElementB(ConcreteElementB concreteElementB) {
// TODO Auto-generated method stub
System.out.println(concreteElementB.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
}
class ConcreteVisitor2 extends Visitor{
@Override
public void VisitConcreteElementA(ConcreteElementA concreteElementA) {
// TODO Auto-generated method stub
System.out.println(concreteElementA.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
@Override
public void VisitConcreteElementB(ConcreteElementB concreteElementB) {
// TODO Auto-generated method stub
System.out.println(concreteElementB.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
}
class ObjectStructure{
private List<Element>elements=new ArrayList<Element>();
public void Attach(Element element) {
elements.add(element);
}
public void Detach(Element element) {
elements.remove(element);
}
public void Accept(Visitor visitor) {
for(Element e:elements) {
e.Accept(visitor);
}
}
}
public class Main{
public static void main(String[] args){
ObjectStructure o=new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
ConcreteVisitor1 v1=new ConcreteVisitor1();
ConcreteVisitor2 v2=new ConcreteVisitor2();
o.Accept(v1);
o.Accept(v2);
}
}
Visitor:是抽象访问者。为该对象结构中的ConerteElement的每一个类声明一个visit操作
ConcreteVisitor:是一个具体的访问者,实现每个有Visitor声明的操作,是每个操作实现的部分
ObjectStructure:能枚举它的元素可以提供一个高层的接口,用来允许访问者访问元素
Element:定义一个accept方法,接收一个访问者对象
ConcreteElement:为具体元素,实现了accept方法
优点:
- 增加新的操作很容易
- 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
缺点:
- 增加新的节点类变得很困难
- 破坏封装