访问者模式
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机。
案例:学校领导访问老师和学生
源代码:
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor {
public static void main(String[] args) {
// TODO Auto-generated method stub
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);
PresidentVisitor pv=new PresidentVisitor();//校长
for(Person s:listperson)
{
pv.Visit(s);
}
DeanVisitor dv=new DeanVisitor();//院长
for(Person s:listperson) {
dv.Visit(s);
}
}
}
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 void setCourse(String course) {
this.course = course;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = 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 void setCourse(String course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = 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()+"成绩:"+student.getGrade());
}
}
}
class DeanVisitor{//院长访问
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()+"成绩:"+student.getGrade());
}
}
}
PresidentVisitor和DeanVisitor都含有visit()方法,因此可以将其提取出来
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
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 s : listperson) {
pv.visit(s);
}
Visitor dv = new DeanVisitor();// 院长
for (Person s : listperson) {
dv.visit(s);
}
}
}
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 void setCourse(String course) {
this.course = course;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = 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 void setCourse(String course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
interface Visitor {
abstract void visit(Person person);
}
class PresidentVisitor implements Visitor {// 校长访问
@Override
public void visit(Person person) {
// TODO Auto-generated method stub
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() + "成绩:" + student.getGrade());
}
}
}
class DeanVisitor implements Visitor {// 院长访问
@Override
public void visit(Person person) {
// TODO Auto-generated method stub
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() + "成绩:" + student.getGrade());
}
}
}
PresidentVisitor和DeanVisitor都含有visit()方法,因此可以将其提取出来将visit重载
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
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 s : listperson) {
if (s instanceof Teacher) {
Teacher teacher = (Teacher) s;
pv.visit(teacher);
} else if (s instanceof Student) {
Student student = (Student) s;
pv.visit(student);
}
}
Visitor dv = new DeanVisitor();// 院长
for (Person s : listperson) {
if (s instanceof Teacher) {
Teacher teacher = (Teacher) s;
dv.visit(teacher);
} else if (s instanceof Student) {
Student student = (Student) s;
dv.visit(student);
}
}
}
}
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 void setCourse(String course) {
this.course = course;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = 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 void setCourse(String course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
interface Visitor {
// 访问老师
abstract void visit(Teacher teacher);
// 访问学生
abstract 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() + "成绩:" + student.getGrade());
}
}
class DeanVisitor 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() + "成绩:" + student.getGrade());
}
}
访问角色增加一个接收访问者的方法
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
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 s : listperson) {
s.accept(pv);
}
Visitor dv = new DeanVisitor();// 院长
for (Person s : listperson) {
s.accept(dv);
}
}
}
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 void setCourse(String course) {
this.course = course;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = 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 void setCourse(String course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
interface Visitor {
// 访问老师
abstract void visit(Teacher teacher);
// 访问学生
abstract 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() + "成绩:" + student.getGrade());
}
}
class DeanVisitor 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() + "成绩:" + student.getGrade());
}
}
访问者模式基本框架:
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ObjectStrucure obs=new ObjectStrucure();
obs.Attach(new ConcreteElementA());
obs.Attach(new ConcreteElementB());
ConcreteVistor1 v1 =new ConcreteVistor1();
ConcreteVistor2 v2=new ConcreteVistor2();
obs.Accept(v1);
System.out.println("--------------------");
obs.Accept(v2);
}
}
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA cea);
public abstract void VisitConcreteElementB(ConcreteElementB ceb);
}
class ConcreteVistor1 extends Visitor{
@Override
public void VisitConcreteElementA(ConcreteElementA cea) {
// TODO Auto-generated method stub
System.out.println(cea.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
@Override
public void VisitConcreteElementB(ConcreteElementB ceb) {
// TODO Auto-generated method stub
System.out.println(ceb.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
}
class ConcreteVistor2 extends Visitor{
@Override
public void VisitConcreteElementA(ConcreteElementA cea) {
// TODO Auto-generated method stub
System.out.println(cea.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
@Override
public void VisitConcreteElementB(ConcreteElementB ceb) {
// TODO Auto-generated method stub
System.out.println(ceb.getClass().toString()+"被"+this.getClass().toString()+"访问");
}
}
class ObjectStrucure
{
private List<Element> eles=new ArrayList<Element>();
public void Attach(Element element)
{
eles.add(element);
}
public void Detach(Element element)
{
eles.remove(element);
}
public void Accept(Visitor visitor)
{
for(Element s:eles)
{
s.Accept(visitor);
}
}
}
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
class ConcreteElementA extends Element
{
@Override
public void Accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.VisitConcreteElementA(this);
}
public void OperationA() {}
}
class ConcreteElementB extends Element
{
public void OperationB() {}
@Override
public void Accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.VisitConcreteElementB(this);
}
}
例题填充:
package Visitor;
import java.util.ArrayList;
import java.util.List;
public class Visitor4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person t1 = new Teacher("张老师", "编程原理", 48);// 老师
Person t2 = new Teacher("王老师", "数据库", 54);
Person s1 = new Student("赵同学", "编程原理", 90);// 学生
Person s2 = new Student("刘同学", "数据库", 82);
ObjeactList list = new ObjeactList();
list.Attach(s1);
list.Attach(s2);
list.Attach(t1);
list.Attach(t2);
Visitor pv = new PresidentVisitor();// 校长
Visitor dv = new DeanVisitor();// 院长
list.Display(pv);
System.out.println("-------------------------");
list.Display(dv);
}
}
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 ObjeactList {
List<Person> listperson = new ArrayList<Person>();
public void Attach(Person element)// 增加
{
listperson.add(element);
}
public void Detach(Person element)// 移除
{
listperson.remove(element);
}
public void Display(Visitor visitor) {// 显示
for (Person s : listperson) {
s.accept(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 void setCourse(String course) {
this.course = course;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = 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 void setCourse(String course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
interface Visitor {
// 访问老师
abstract void visit(Teacher teacher);
// 访问学生
abstract 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() + "成绩:" + student.getGrade());
}
}
class DeanVisitor 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() + "成绩:" + student.getGrade());
}
}
访问者模式的应用
何时使用?
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类时。
方法
- 在被访问的类里面添加一个对外提供接待访问者的接口。
优点
- 符合单一职责原则。
- 优秀的扩展性。
- 灵活性非常高。
缺点
- 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的。
- 具体元素变更比较困难。
- 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素。
使用场景
- 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖与其具体类的操作,也就是用迭代器模式已经不能胜任的情景。
- 需要对一个对结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象。