概念

访问者模式:允许一个或者多个操作应用到一组对象上,解耦操作和对象本身。

使用场景

一般来说,访问者模式针对的是一组类型不同的对象(PdfFile、PPTFile、WordFile)。不 过,尽管这组对象的类型是不同的,但是,它们继承相同的父类(ResourceFile)或者实 现相同的接口。在不同的应用场景下,我们需要对这组对象进行一系列不相关的业务操作 (抽取文本、压缩等),但为了避免不断添加功能导致类(PdfFile、PPTFile、WordFile) 不断膨胀,职责越来越不单一,以及避免频繁地添加功能导致的频繁代码修改,我们使用访问者模式,将对象操作解耦,将这些业务操作抽离出来,定义在独立细分的访问者类 (Extractor、Compressor)中。

为什么支持双分派的语言不需要访问者模式?

Single Dispatch,

指的是执行哪个对象的方法,根据对象的运行时类型来决定;执行对象的哪个方法,根据方法参数的编译时类型来决定。

Double Dispatch

指的是执行哪个对象的方法,根据对象的运行时类型来决定;执行对象的哪个方法,根据方法参数的运行时类型来决定。

Single 和 Double

Single Dispatch 之所以称为“Single”,是因为执行哪个对象的哪个方法,只跟“对象”的运行时类型有关。Double Dispatch 之所以称为“Double”,是因为执行哪个对象的哪个方法,跟“对象”和“方法参数”两者的运行时类型有关。

Java的Single Dispatch

Java 支持多态特性,代码可以在运行时获得对象的实际类型(也就是前面提到的运行时类 型),然后根据实际类型决定调用哪个方法。尽管 Java 支持函数重载,但 Java 设计的函数重载的语法规则是,并不是在运行时,根据传递进函数的参数的实际类型,来决定调用哪个重载函数而是在编译时,根据传递进函数的参数的声明类型(也就是前面提到的编译时 类型),来决定调用哪个重载函数。也就是说,具体执行哪个对象的哪个方法,只跟对象的运行时类型有关,跟参数的运行时类型无关。所以,Java 语言只支持 Single Dispatch。

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ParentClass {
public void f() {
System.out.println("I am ParentClass's f().");
}
}
public class ChildClass extends ParentClass {
public void f() {
System.out.println("I am ChildClass's f().");
}
}
public class SingleDispatchClass {
public void polymorphismFunction(ParentClass p) {
p.f();
}
public void overloadFunction(ParentClass p) {
System.out.println("I am overloadFunction(ParentClass p).");
}
public void overloadFunction(ChildClass c) {
System.out.println("I am overloadFunction(ChildClass c).");
}
}
public class DemoMain {
public static void main(String[] args) {
SingleDispatchClass demo = new SingleDispatchClass();
ParentClass p = new ChildClass();
// 执行哪个对象的方法,由对象的实际类型决定。
// 这里对象p的实例化是ChildClass,所以调用了child的f方法。
demo.polymorphismFunction(p);
// 执行对象的哪个方法,由参数对象的声明类型决定
// 这里指的是执行SingleDispatchClass的哪一个overloadFunction方法
// 他取决于参数p声明的类型,即ParentClass
demo.overloadFunction(p);
}
}

image-20230627112245628

注:Java作为Single Dispatch,执行重载方法的时候,只会根据执行方法时传递的参数声明时的类型来执行,并不会关注他到底实例化了哪一个对象。

参考

《设计模式之美》