访问者模式
访问者模式:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用与这些元素的新的操作。可以遍历不同的对象。
角色:1.Visitor抽象访问者:声明访问者可以访问哪些元素。
2.ConcreteVisitor具体访问者:访问者访问到一个类后应该做什么。
3.Element抽象元素:声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。
4.ConcreteElement具体元素:实现accept方法,通常是visitor.visit(this)。
5.ObjectStruture结构对象:元素产生者,很少抽象出这个角色。
适用场景:需要对一个对象结构中的对象进行很多不同并且不想关的操作。
具体实现:
通用实现
1.创建抽象元素
/**
* 抽象元素
*/
public abstract class Element {
//每个元素都有一个成绩和姓名
private int grade = 0;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
//我允许一个访问者访问我
public abstract void accept(IVisitor visitor);
}
2.创建具体元素1和2.各自属性有细微不同
/**
* 具体访问者1
* 访问者1存在money属性
*/
public class ConcreteElement1 extends Element {
private int money = 0;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* 具体元素2
* 具体元素2有职位属性
*/
public class ConcreteElement2 extends Element {
private String position = "";
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
3.创建访问者接口
/**
* 访问者接口
*/
public interface IVisitor {
//可以访问哪些对象
public void visit(ConcreteElement1 concreteElement1);
public void visit(ConcreteElement2 concreteElement2);
}
4.创建具体访问者
/**
* 具体访问者
*/
public class Visitor implements IVisitor {
@Override
public void visit(ConcreteElement1 concreteElement1) {
System.out.println(this.getConcreteElement1Info(concreteElement1));
}
@Override
public void visit(ConcreteElement2 concreteElement2) {
System.out.println(this.getConcreteElement2Info(concreteElement2));
}
public String getConcreteElement1Info(ConcreteElement1 concreteElement1){
String info = "姓名:"+concreteElement1.getName();
info+=" 成绩:"+concreteElement1.getGrade();
info+=" 钱:"+concreteElement1.getMoney();
return info;
}
public String getConcreteElement2Info(ConcreteElement2 concreteElement2){
String info = "姓名:"+concreteElement2.getName();
info+=" 成绩:"+concreteElement2.getGrade();
info+=" 职位:"+concreteElement2.getPosition();
return info;
}
}
5.创建场景测试类
/**
* 场景测试类
*/
public class Client {
public static void main(String[] args) {
IVisitor visitor = new Visitor();
for (Element e:
getMock()) {
e.accept(visitor);
}
}
//生产几个元素模拟
public static List<Element> getMock(){
ConcreteElement1 zhangshan = new ConcreteElement1();
zhangshan.setMoney(1000);
zhangshan.setName("张三");
zhangshan.setGrade(79);
ConcreteElement1 lisi = new ConcreteElement1();
lisi.setMoney(2356);
lisi.setName("李思");
lisi.setGrade(84);
ConcreteElement2 wangwu = new ConcreteElement2();
wangwu.setPosition("经理");
wangwu.setName("王五");
wangwu.setGrade(99);
List<Element> list = new ArrayList<>();
list.add(zhangshan);
list.add(lisi);
list.add(wangwu);
return list;
}
}
统计功能(统计成绩之和,元素1的成绩乘5,元素2的成绩乘10)
1.修改访问者接口
/**
* 访问者接口
*/
public interface IVisitor {
//可以访问哪些对象
public void visit(ConcreteElement1 concreteElement1);
public void visit(ConcreteElement2 concreteElement2);
//获取总成绩之和
public int getTotalGrade();
}
2.修改访问者实现类
/**
* 具体访问者
*/
public class Visitor implements IVisitor {
//元素一的成绩之和
private int allGrade1 = 0;
//元素二的成绩之和
private int allGrade2 = 0;
@Override
public void visit(ConcreteElement1 concreteElement1) {
this.AddGrade1(concreteElement1.getGrade());
System.out.println(this.getConcreteElement1Info(concreteElement1));
}
@Override
public void visit(ConcreteElement2 concreteElement2) {
this.AddGrade2(concreteElement2.getGrade());
System.out.println(this.getConcreteElement2Info(concreteElement2));
}
//获取元素一的信息
public String getConcreteElement1Info(ConcreteElement1 concreteElement1){
String info = "姓名:"+concreteElement1.getName();
info+=" 成绩:"+concreteElement1.getGrade();
info+=" 钱:"+concreteElement1.getMoney();
return info;
}
//获取元素二的信息
public String getConcreteElement2Info(ConcreteElement2 concreteElement2){
String info = "姓名:"+concreteElement2.getName();
info+=" 成绩:"+concreteElement2.getGrade();
info+=" 职位:"+concreteElement2.getPosition();
return info;
}
//获得元素一的成绩之和
private void AddGrade1(int grade){
this.allGrade1+=grade*5;
}
//获得元素二的成绩之和
private void AddGrade2(int grade){
this.allGrade2+=grade*10;
}
@Override
public int getTotalGrade() {
return this.allGrade1+this.allGrade2;
}
}
3.修改场景测试类
/**
* 场景测试类
*/
public class Client {
public static void main(String[] args) {
IVisitor visitor = new Visitor();
for (Element e:
getMock()) {
e.accept(visitor);
}
System.out.println("总成绩为:"+visitor.getTotalGrade());
}
//生产几个元素模拟
public static List<Element> getMock(){
ConcreteElement1 zhangshan = new ConcreteElement1();
zhangshan.setMoney(1000);
zhangshan.setName("张三");
zhangshan.setGrade(79);
ConcreteElement1 lisi = new ConcreteElement1();
lisi.setMoney(2356);
lisi.setName("李思");
lisi.setGrade(84);
ConcreteElement2 wangwu = new ConcreteElement2();
wangwu.setPosition("经理");
wangwu.setName("王五");
wangwu.setGrade(99);
List<Element> list = new ArrayList<>();
list.add(zhangshan);
list.add(lisi);
list.add(wangwu);
return list;
}
}
多个访问者
1.修改访问者接口
/**
* 访问者接口
*/
public interface IVisitor {
//可以访问哪些对象
public void visit(ConcreteElement1 concreteElement1);
public void visit(ConcreteElement2 concreteElement2);
}
2.添加二号访问者,二号访问者进行统计成绩
/**
* 具体访问者2
* 统计总成绩
*/
public class Visitor2 implements IVisitor {
//元素一的成绩之和
private int allGrade1 = 0;
//元素二的成绩之和
private int allGrade2 = 0;
@Override
public void visit(ConcreteElement1 concreteElement1) {
this.AddGrade1(concreteElement1.getGrade());
}
@Override
public void visit(ConcreteElement2 concreteElement2) {
this.AddGrade2(concreteElement2.getGrade());
}
//获得元素一的成绩之和
private void AddGrade1(int grade){
this.allGrade1+=grade*5;
}
//获得元素二的成绩之和
private void AddGrade2(int grade){
this.allGrade2+=grade*10;
}
//获得总成绩
public int getTotalGrade() {
return this.allGrade1+this.allGrade2;
}
}
3.修改一号访问者,一号访问者只展示基础数据
/**
* 具体访问者1
* 只展示基础信息
*/
public class Visitor implements IVisitor {
@Override
public void visit(ConcreteElement1 concreteElement1) {
System.out.println(this.getConcreteElement1Info(concreteElement1));
}
@Override
public void visit(ConcreteElement2 concreteElement2) {
System.out.println(this.getConcreteElement2Info(concreteElement2));
}
//获取元素一的信息
public String getConcreteElement1Info(ConcreteElement1 concreteElement1){
String info = "姓名:"+concreteElement1.getName();
info+=" 成绩:"+concreteElement1.getGrade();
info+=" 钱:"+concreteElement1.getMoney();
return info;
}
//获取元素二的信息
public String getConcreteElement2Info(ConcreteElement2 concreteElement2){
String info = "姓名:"+concreteElement2.getName();
info+=" 成绩:"+concreteElement2.getGrade();
info+=" 职位:"+concreteElement2.getPosition();
return info;
}
}
4.修改场景测试类
/**
* 场景测试类
*/
public class Client {
public static void main(String[] args) {
Visitor visitor = new Visitor();
Visitor2 visitor2 = new Visitor2();
for (Element e:
getMock()) {
e.accept(visitor); //接受一号访问者访问
e.accept(visitor2); //接受二号访问者访问
}
System.out.println("总成绩为:"+visitor2.getTotalGrade());
}
//生产几个元素模拟
public static List<Element> getMock(){
ConcreteElement1 zhangshan = new ConcreteElement1();
zhangshan.setMoney(1000);
zhangshan.setName("张三");
zhangshan.setGrade(79);
ConcreteElement1 lisi = new ConcreteElement1();
lisi.setMoney(2356);
lisi.setName("李思");
lisi.setGrade(84);
ConcreteElement2 wangwu = new ConcreteElement2();
wangwu.setPosition("经理");
wangwu.setName("王五");
wangwu.setGrade(99);
List<Element> list = new ArrayList<>();
list.add(zhangshan);
list.add(lisi);
list.add(wangwu);
return list;
}
}