访问者模式Visitor

访问者模式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方法

优点

  • 增加新的操作很容易
  • 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。

缺点:

  • 增加新的节点类变得很困难
  • 破坏封装
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值