设计模式:访问者模式

news/2024/11/22 22:35:57/

一、定义

封装一些作用于某种数据结构中各元素的操作,在不改变现有类结构的前提下,增加新的操作或算法

二、角色

Visitor:抽象访问者,接口或者抽象类,为每一个元素(Element)声明一个访问的方法。
ConcreteVisitor:具体访问者,实现抽象访问者中的方法,即对每一个元素都有其具体的访问行为。
Element:抽象元素,接口或者抽象类,定义一个accept方法,能够接受访问者(Visitor)的访问。
ConcreteElementA、ConcreteElementB:具体元素,实现抽象元素中的accept方法,通常是调用访问者提供的访问该元素的方法。

三、使用场景

  • 对象结构比较稳定,很少改变,但是经常需要在此对象结构上定义新的操作行为时。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。

四、使用案例

老师访问学生成绩

1、被访问者

定义被访问者学生。抽象了一个学生基类,随机数来模拟总成绩。

public abstract class Students {public String name;public int totalScore; // 总成绩Students(String aName) {name = aName;totalScore = new Random().nextInt(100);}public abstract void accept(Visitor visitor);
}
// 体育生,随机数模拟成绩
public class SportsStudents extends Students {public int sports;public SportsStudents(String aName) {super(aName);sports = new Random().nextInt(100);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 美术生,随机数模拟成绩
public class ArtStudents extends Students {public int art;public ArtStudents(String aName) {super(aName);art = new Random().nextInt(100);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}

被访问者学生,这个类很稳定。不需要再添加其他信息来“污染”被访问者了。

2、访问者

先抽象出访问者的访问方法visit

public interface Visitor {public void visit(ArtStudents artStudents);public void visit(SportsStudents sportsStudents);
}

定义两个访问者,一个班主任,他关注总成绩和特长科目成绩。另一个特长老师,他只关心特长科目成绩。

// 班主任
public class HeadmasterTeacherVisitor implements Visitor {private static String TAG = ArtStudents.class.getSimpleName();@Overridepublic void visit(ArtStudents artStudents) {Log.d(TAG,"name = " + artStudents.name);Log.d(TAG,"totalScore = " + artStudents.totalScore);Log.d(TAG,"art = " + artStudents.art);}@Overridepublic void visit(SportsStudents sportsStudents) {Log.d(TAG,"name = " + sportsStudents.name);Log.d(TAG,"totalScore = " + sportsStudents.totalScore);Log.d(TAG,"sports = " + sportsStudents.sports);}
}// 特长老师
public class SpecialTeacherVisitor implements Visitor {private static String TAG = SpecialTeacherVisitor.class.getSimpleName();@Overridepublic void visit(ArtStudents artStudents) {Log.d(TAG,"name = " + artStudents.name);Log.d(TAG,"art = " + artStudents.art);}@Overridepublic void visit(SportsStudents sportsStudents) {Log.d(TAG,"name = " + sportsStudents.name);Log.d(TAG,"sports = " + sportsStudents.sports);}
}

访问者只关注他想关注的信息,不需要多于的操作。这里体现了访问操作的不同且不相关。

3、访问

访问的核心就是一个遍历。根据不同的访问者和被访问者达到不同的操作目的。

public class StudentsList {List<Students> list = new LinkedList<Students>();public StudentsList() {list.add(new ArtStudents("jack"));list.add(new ArtStudents("john"));list.add(new SportsStudents("lily"));list.add(new SportsStudents("sky"));}public void showStudentschievement(Visitor visitor) {for (Students students : list) {students.accept(visitor);}}
}

模拟把所有学生放到一个list里面。遍历的时候,被访问者students调用accept访问来同意访问。

4、调用

StudentsList list = new StudentsList();list.showStudentschievement(new HeadmasterTeacherVisitor());
list.showStudentschievement(new SpecialTeacherVisitor());

五、在Android中的使用

在编译期注解中,编译期注解核心原理依赖APT(Annotation Processing Tools),著名的开源库比如ButterKnife、Dagger、Retrofit都是基于APT。

六、优缺点

优点:

  • 各角色职责分离,符合单一原则
  • 扩展十分方便,灵活
  • 数据结构和数据结构上的操作解耦

缺点:

  • 被访问者对访问者公布了细节,违反迪米特原则
  • 被访问者要改动的时候,修改十分麻烦。
  • 访问者和被访者为了达到不同的行为目的的时候,为了区分依赖了类的不同,没有依赖抽象。

http://www.ppmy.cn/news/45199.html

相关文章

电磁兼容(EMC)的标准与测试内容

在国际范围上&#xff0c;电磁兼容标准的制定已经有了70多年的发展历程&#xff0c;最早为了保护无线电通信和广播&#xff0c;国际无线电干扰特别委员会&#xff08;CISPR&#xff09;对各种用电设备和系统提出了相关的电磁干扰发射限值和测量方法。到了20世纪60&#xff5e;7…

Linux查看端口被进程占用的方法

一、 lsof命令 lsof(list open files)命令可以列出当前系统中打开的所有文件&#xff0c;包括网络端口。可以使用lsof命令查看某个端口被哪个进程占用。 具体的命令为&#xff1a;sudo lsof -i :端口号&#xff0c;其中端口号为需要查询的端口号。 二、 netstat命令 使用nets…

第一节 法学

目录 法学的概念法学的性质 实践性构成了法学的学问性质 法学的研究对象 1.法律制度问题&#xff08;X法律制度&#xff09;2. 社会现实或社会生活关系问题 (Y社会现实/社会关系)3.法律制度与社会现实之间如何对应的问题 &#xff08;Yf(x) f为什么函数&#xff09; 法学的概…

使用Python创建分形图案

分形是无限复杂的模式&#xff0c;在不同的尺度上具有自相似性。例如&#xff0c;一棵树的树干会分裂成更小的树枝。这些树枝又分裂成更小的树枝&#xff0c;以此类推。 通过编程的方式生成分形&#xff0c;可以将简单的形状变成复杂的重复图案。 本文将探讨如何利用一些简单…

机械硬盘提示格式化的常见原因|3种数据恢复方法

机械硬盘是电脑存储设备中的一种&#xff0c;它的存储容量比较大&#xff0c;通常采用机械运动的方式记录数据。 其内部结构由多个盘片和磁头组成&#xff0c;盘片层层叠放在一起并通过主轴转动&#xff0c;磁头则通过磁臂上下移动并接触盘片表面进行读写操作。但是在日常使用电…

【算法题】2594. 修车的最少时间

题目&#xff1a; 给你一个整数数组 ranks &#xff0c;表示一些机械工的 能力值 。ranksi 是第 i 位机械工的能力值。能力值为 r 的机械工可以在 r * n2 分钟内修好 n 辆车。 同时给你一个整数 cars &#xff0c;表示总共需要修理的汽车数目。 请你返回修理所有汽车 最少 需…

2-修改example适用于不同开发板

1.问题 手上只有基于nRF52811芯片的BMD360开发板,与pca10056e开发板同一个芯片.所以pca10056e的example都可以适用于BMD360开发板,只需要修改开发板相同的输入输出硬件管脚即可.因为BMD360开发板与pca10056e开发板的输入输出管脚不同. 而BMD360开发板输入输出管脚于PCA10040相同…

Elasticsearch:使用 Elastic APM 监控 Android 应用程序(二)

在我之前的文章 “Elasticsearch&#xff1a;使用 Elastic APM 监控 Android 应用程序&#xff08;一&#xff09;” 中&#xff0c;我详述了如何使用 Elastic APM 来监控 Android 应用程序。在今天的文章中&#xff0c;我来详述如何部署 Elastic Stack&#xff0c;并使用文章中…