
在本讲,我们来学习一下行为型模式里面的第九个设计模式,即访问者模式。
概述先来看一下访问者模式的概念。
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
上述访问者模式的概念看完之后,相信大家都懵了,没关系,下面我给大家解释解释。
访问者模式是说封装一些作用于某种数据结构中的各元素的操作,这句话表示什么含义呢?其实就是说将数据结构和元素的操作进行了一个分离,分离之后,访问者模式就可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
可能我这样解释了之后,大家可能还不是特别理解,但没关系,后面我会通过一个案例再来对访问者模式进行一个讲解,相信大家一定能明白访问者模式的概念。
知道了访问者模式的概念之后,接下来,我们就来看看访问者模式的结构,也就是它里面所拥有的角色。
结构访问者模式包含以下主要角色:
抽象访问者(Visitor)角色:定义了对每一个元素(Element)访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数(即Element抽象元素类的实现类的个数)是一样的,从这点不难看出,访问者模式要求元素类的个数不能改变。
看完抽象访问者角色的概念,哎,你会发现概念中提到了元素这一东东,这不禁让我们想到了集合,因为集合里面存储的就是元素,所以在这儿必定会有一个容器性质的对象,这个留待我们后续再说。
另外,我也不知道大家有没有看懂以上抽象访问者角色的概念,要是没看懂的话,我这里再来重新解释一遍。一般来说,我们会将抽象访问者角色定义成一个接口,然后在该接口中定义对每一个元素访问的方法,当然了,方法的参数就是可以访问的元素,所以有多少个具体元素角色类,那么该接口里面就要提供多少个方法。这也就是说,理论上讲,方法个数应与元素类个数(即Element抽象元素类的实现类的个数)是一样的,从这点不难看出,访问者模式要求元素类的个数不能改变,如果改变了的话,那么你就不能使用访问者模式了。所以,使用访问者模式的要求还是比较苛刻的,相信大家也不难看出访问者模式在实际开发中使用的其实并不是特别多!
具体访问者(Concrete Visitor)角色:给出对每一个元素类访问时所产生的具体行为。说到底其实就是对抽象访问者角色里面方法的一个实现。
抽象元素(Element)角色:定义了一个接受访问者的方法(即accept),其意义是指,每一个元素都要可以被访问者访问。注意了,该角色只是定义了一个规范,而该规范由谁来实现呢?由具体元素角色类来实现。
具体元素(Concrete Element)角色:提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
对象结构(Object Structure)角色:定义当中所提到的对象结构(其实指的就是访问者模式概念里面所提到的数据结构),对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它会包含一组元素(Element),并且可以迭代这些元素,供访问者访问。
相信大家看完以上访问者模式所包含的角色之后,应该是一脸懵逼的,不过这没关系,下面我会通过一个具体的案例来让大家再深入认识一下以上访问者模式的五个角色。
访问者模式案例接下来,按照惯例我们通过一个案例来让大家再去理解一下访问者模式的概念,以及它里面所包含的角色,而这个案例就是给宠物喂食。
分析现在养宠物的人特别多,我们就以这个为例,当然宠物还分为狗、猫等,要给宠物喂食的话,不仅主人可以喂,其他人也是可以进行喂食的。
接下来,我们就来分析一下访问者模式里面的各个角色在该案例中分别是由谁来充当的。
分析完之后,我们就来看一下下面这张类图。
看完以上类图之后,接下来我们就要逐一分析以上类图中所涉及到的类和接口,以及类和类、类和接口之间的关系了。
首先,我们先来看一下以上类图的左侧部分,可以看到上面有一个接口,名称为Animal,很显然,该接口充当的就是访问者模式里面的抽象元素角色。而且,该接口里面还提供了一个accept方法,很明显,该方法就是用来接受访问者访问的。不过大家要注意了,该方法还须接收一个Person类型的参数,而Person就是一个接口,这在类图的右侧部分就能看到,后面我再来讲解该接口啊!
对于Animal接口来说,它有两个子实现类,一个是Dog(即宠物狗类),一个是Cat(即宠物猫类),显然它俩都得实现Animal接口并重写里面的accept抽象方法,注意,它俩充当的是访问者模式里面的具体元素角色。
然后,我们再来看一下以上类图的右侧部分,可以看到上面也有一个接口,名称为Person,很显然,该接口充当的就是访问者模式里面的抽象访问者角色。而且,该接口里面还提供了两个feed方法,
实现。。。