访问者模式:从介绍到实践
百万级高并发WebRTC流媒体服务器设计与开发
download:https://www.zxit666.com/1305/
01什么是访客模式?
访问者模式的定义如下,是指在不改变数据结构的情况下,提前定义新的操作。
封装了一些作用于数据结构中元素的操作,可以在不改变数据结构的情况下定义作用于这些元素的新操作。
但在实际应用中,我发现有些例子并非如此。在一些例子中,没有稳定的数据结构,但有稳定的算法。在亦舒看来,访客模式是:固定不变的,开放可变的。
先说一个生活中的例子:一个科学家凭记忆面试。众所周知,科学家在接受采访时,肯定有一些程序上的限制。你是不可能随便提问的。我们假设这个过程是:先问科学家的学校经历,再谈你的工作经历,最后谈你的科研成果。那么这个过程中固定的是什么呢?固定的是面试流程。有什么变化?改变的是,不同的记者可能会根据他们的学校经历提出不同的问题。
按照我们之前的理解,访客模式其实就是把不可改变的东西固定下来,把变化打开。然后我们可以抽象出科学家的采访。
首先需要有一个Visitor类,定义了一些外部(记者)可以做的事情(提问学校经历、工作经历、科研成果)。
公共接口访问者{
public void askSchoolExperience(字符串名);
public void askWorkExperience(字符串名);
public void askScienceAchievement(字符串名);
}
然后声明一个XinhuaVisitor类来实现Visitor类,意思是新华社的一个记者(访问者)要访问科学家。
公共类XinhuaVisitor实现访问者{
@覆盖
public void askSchoolExperience(字符串名称){
System.out.printf("请问%s:你在学校最大的成就是什么?n ",名称);
}
@覆盖
public void askWorkExperience(字符串名称){
System.out.printf("请问%s:工作中最难忘的事是什么?n ",名称);
}
@覆盖
public void askScienceAchievement(字符串名称){
System.out.printf("请问%s:最大的科研成果是什么?",姓名);
}
}
然后声明一个科学家类,说明是科学家。科学家通过一个accept()方法接收记者(访问者)的采访申请并存储。科学家定义了一种面试方法,把面试过程固定死。只有我教你问什么,我才会让你(记者)提问。
公共类科学家{
私人访问者访问者;
私有字符串名称;
私人科学家(){}
公共科学家(字符串名称){
this.name = name
}
公共void接受(访问者访问者){
this.visitor =访问者;
}
公开无效面试(){
system . out . println("-");
System.out.println(" -开始说学校经历-");
visitor.askSchoolExperience(姓名);
System.out.println(" -开始说工作经历-");
visitor.askWorkExperience(名称);
System.out.println(" -开始说科研成果-");
visitor.askScienceAchievement(姓名);
}
}
最后,我们声明一个场景类客户端来模拟面试过程。
公共类客户端{
公共静态void main(String[] args) {
科学家杨=新科学家();
yang . accept(new XinhuaVisitor());
yang . interview();
}
}
操作的结果是:
-访问开始
-开始谈论学校经历-
请问,杨振宁:你在学校最大的成就是什么?
-开始谈论工作经历-
请问杨振宁:你在工作中最难忘的观点是什么?
-开始谈论科研成果-
请问杨振宁:最大的科研成就是什么?
看到这里,大家对访客模式的本质(固定不变,开放可变)有了更感性的认识。在这个例子中,不变的、固定的是面试过程。改变的是你可以问不同的问题。
一般来说,访问者模式的类结构如下图所示:
访问者访问者界面。访问者定义访问者可以做什么。这就需要你分析什么是可改变的,把这些可改变的内容抽象成一个访问者接口方法,把它开放出来。被访问者的信息实际上是通过访问者的参数传递的。
具体访问者。特定访问者定义了特定类型访问者的实现。对于新华社记者来说,他们更关心杨振宁的科学成就,所以提问时更倾向于挖掘成就。但对于青年报记者来说,他们的读者是青少年,他们更关注杨振宁在学习和工作中的精神。
元素具体元素。这指的是特定的被访问的类,在我们的例子中,是科学家类。一般情况下,我们会提供一个accept()方法来接收访问者参数,这将相当于接受它的模型应用。然而,这种方法不是必需的。只要能得到visitor对象,就可以定义这个参数传递。
对于访问者模式,最重要的是访问者、具体访问者和元素。Visitor和ConcreteVisitor定义了访问者具体能做什么,被访问者的参数通过参数传递给访问者。元素通过各种方法获取被访问的对象,通常是通过accept()方法,但这不是绝对的。
应该注意的是,我们对设计模式的研究侧重于理解类之间的关系以及它们所传达的信息。至于如何传递,是通过accept()方法还是通过构造函数,都不是重点。