设计模式——访问者模式

一、访问者模式
在这里插入图片描述
Visitor:是抽象访问者。为该对象结构中的ConerteElement的每一个类声明一个visit操作
ConcreteVisitor:是一个具体的访问者,实现每个有Visitor声明的操作,是每个操作实现的部分
ObjectStructure:能枚举它的元素可以提供一个高层的接口,用来允许访问者访问元素
Element:定义一个accept方法,接收一个访问者对象
ConcreteElement:为具体元素,实现了accept方法
2、代码:

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);
	}
}

访问者模式:
(1)访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
(2)主要将数据结构与数据操作分离,解决数据结构和操作耦合性问题。
(3)访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口。

3、优点:
1)增加新的操作很容易
2)访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
4、缺点:
1)增加新的节点类变得很困难
2)破坏封装

二、实例

1、例题背景:
校长和院长检查教师和学生
校长和院长检查教师的工作情况和学生的学习情况,
校长关注教师的教学工作量,学生学习的课程;
院长关注教师的课程,学生的学习成绩。
由于校长和院长对于教师和学生的关注点是不一样的,这就需要对教师和学生进行不同的处理
教师的工作和学生的学习相对稳定,访问者和处理方式多种多样。
如何在不更改数据元素结构(教师的工作和学生的学习)的前提下,在运行时根据需要透明地为其动态添加新的操作?

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);
		}
	}
}
结果为:
校长 访问老师 张老师学时:48
校长 访问老师 王老师学时:54
校长 访问学生 赵同学课程:编译原理
校长 访问学生 刘同学课程:数据库
院长 访问老师 张老师课程:编译原理
院长 访问老师 王老师课程:数据库
院长 访问学生 赵同学成绩:90
院长 访问学生 刘同学成绩:82

改进:发现类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){
Listlistperson=new ArrayList();
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);
}
}
}

**存在问题:**接口和实现里只通过一个visit方法,进行处理,那么就需要在这个visit方法中进行判断,然后分别处理。这就导改了if-else逻辑的嵌套以及类型的强制转换,难以扩展和维护,如果再增加检查“图书馆馆员”的工作, PresidentVisitor和DeanVisitor就会很复杂。当类型较多时,就需要增加分支判断。
解决方法: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);
			}
		}
	}
}

**出现问题:**这样就把判断转移到了客户端。
这种public void visit(Teacher teacher)或public void visit(Student 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());
}
}
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 p=new PresidentVisitor();//创建校长
		Visitor d=new DeanVisitor();//院长
		for(Person b:listperson) {
			b.accept(p);
		}
		System.out.println("==================");
		for(Person b:listperson) {
			b.accept(d);
		}
	}
}

客户端改进

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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值