访问者模式(Visitor)
===================
ps:这个是作业来的,还没写完这份文档,先post上来,反正也写完了多分派的一些重点内容。
访问者模式主要内容有看两点,第一个是访问对象结构(比如遍历一颗树上的对象节点什么的),第二个就是在单分派语言上实现二分派啦。在《设计模式》中的解释是,访问者模式可以让你在不改动原有对象结构(代码)的基础上给它们添加新方法。
照例来段原文,方便自己解释
> Represent an operation to be performed on the elements of an object
> structure. Visitor lets you define a new operation without changing the
> classes of the elements on which it operates.
栗子
-----
###多分派
假如你知道什么是多分派(multiple dispatch)可以跳过这一段。
我们来模拟一个动物吃食物的过程,先看下参战双方,动物这边有Cat和Dog,都是继承自Aninamal,并重写了其中的3个不同签名的eat方法。
```java
public class Animal {
public void eat(Food food){
}
public void eat(Fish fish){
}
public void eat(Mutton mutton){
}
}
public class Cat extends Animal{
@Override
public void eat(Food food){
}
@Override
public void eat(Fish fish){
}
@Override
public void eat(Mutton mutton){
}
}
public class Dog extends Animal{
@Override
public void eat(Food food){
}
@Override
public void eat(Fish fish){
}
@Override
public void eat(Mutton mutton){
}
}
```
下面是我们的食物类,有Fish,Mutton,继承自Food。
```java
public class Food{}
public class Mutton extends Food{}
public class Fish extends Food{}
```
大家都知道,java的多态(Polimorphism)是在运行时动态地根据具体对象来选择实际要调用哪个方法(Override)。另外需要提一下的是重写(Overload),重写是根据方法的不同参数来调用不同的方法,不过,jvm在预处理的时候实际上是把签名合并到方法名中去了,所以实际上是两个不同方法名的方法。
好了,我们开始先下面的测试代码
```java
Animal animal;
Food food;
Mutton mutton;
animal = new Dog();
food = new Fish();
mutton = new Mutton();
animal.eat(mutton);
animal.eat(food);
```
最后一条语句,根据我们了解到的java的多态性,我们知道这时的animal.eat方法一定是Dog里面重写的那个eat方法,这个毋庸置疑。
但是,dog里面重写了3个不同签名的eat方法,这时调用的是哪一个呢?没错,是eat(Food),而不是eat(Fish),虽然传给eat方法的确实是fish对象,虽然挂了个Food的外号。只有倒数第二条语句(animal.eat(mutton))才会用到Overload的福利,成功调用到了eat(Mutton)。
为毛?为毛?为毛?因为java是单分派语言,附带上一大票单分派战友(c#,c++,python)。
单分派的意思是,它只会去根据一条继承链来寻找合适的对象,java(以及大部分面向对象语言)中的实现是用在了调用的对象上面(这个是写死的),也就是发起调用的对象。
这就是为什么我们的animal可以成功地被辨识为dog,但是方法里面的参数中的food就不能在运行时被辨识为Fish。
那末这样子就很容易知道多分派语言是什么啦。看下面的老虎机图片,每个滚轴都代表一条继承链的话,那么单分派语言就只能有一个滚轴,而且是定死在那个位置滚(只对调用方法的对象进行分派),而多分派语言就像下面的老虎机,有好多个对象都可以动态地分派。
多分派语言比较有名的是(Common Lisp),哇,函数式编程语言,看起来就很高大上。
[老虎机图片]()
ps: java,c++中的单分派具体实现在这里没有分析,有兴趣可以看参考资料(),common lisp完全没看过,有时间再看下。有关多分派的内容,请看参考资料()。
===================
ps:这个是作业来的,还没写完这份文档,先post上来,反正也写完了多分派的一些重点内容。
访问者模式主要内容有看两点,第一个是访问对象结构(比如遍历一颗树上的对象节点什么的),第二个就是在单分派语言上实现二分派啦。在《设计模式》中的解释是,访问者模式可以让你在不改动原有对象结构(代码)的基础上给它们添加新方法。
照例来段原文,方便自己解释
> Represent an operation to be performed on the elements of an object
> structure. Visitor lets you define a new operation without changing the
> classes of the elements on which it operates.
栗子
-----
###多分派
假如你知道什么是多分派(multiple dispatch)可以跳过这一段。
我们来模拟一个动物吃食物的过程,先看下参战双方,动物这边有Cat和Dog,都是继承自Aninamal,并重写了其中的3个不同签名的eat方法。
```java
public class Animal {
public void eat(Food food){
}
public void eat(Fish fish){
}
public void eat(Mutton mutton){
}
}
public class Cat extends Animal{
@Override
public void eat(Food food){
}
@Override
public void eat(Fish fish){
}
@Override
public void eat(Mutton mutton){
}
}
public class Dog extends Animal{
@Override
public void eat(Food food){
}
@Override
public void eat(Fish fish){
}
@Override
public void eat(Mutton mutton){
}
}
```
下面是我们的食物类,有Fish,Mutton,继承自Food。
```java
public class Food{}
public class Mutton extends Food{}
public class Fish extends Food{}
```
大家都知道,java的多态(Polimorphism)是在运行时动态地根据具体对象来选择实际要调用哪个方法(Override)。另外需要提一下的是重写(Overload),重写是根据方法的不同参数来调用不同的方法,不过,jvm在预处理的时候实际上是把签名合并到方法名中去了,所以实际上是两个不同方法名的方法。
好了,我们开始先下面的测试代码
```java
Animal animal;
Food food;
Mutton mutton;
animal = new Dog();
food = new Fish();
mutton = new Mutton();
animal.eat(mutton);
animal.eat(food);
```
最后一条语句,根据我们了解到的java的多态性,我们知道这时的animal.eat方法一定是Dog里面重写的那个eat方法,这个毋庸置疑。
但是,dog里面重写了3个不同签名的eat方法,这时调用的是哪一个呢?没错,是eat(Food),而不是eat(Fish),虽然传给eat方法的确实是fish对象,虽然挂了个Food的外号。只有倒数第二条语句(animal.eat(mutton))才会用到Overload的福利,成功调用到了eat(Mutton)。
为毛?为毛?为毛?因为java是单分派语言,附带上一大票单分派战友(c#,c++,python)。
单分派的意思是,它只会去根据一条继承链来寻找合适的对象,java(以及大部分面向对象语言)中的实现是用在了调用的对象上面(这个是写死的),也就是发起调用的对象。
这就是为什么我们的animal可以成功地被辨识为dog,但是方法里面的参数中的food就不能在运行时被辨识为Fish。
那末这样子就很容易知道多分派语言是什么啦。看下面的老虎机图片,每个滚轴都代表一条继承链的话,那么单分派语言就只能有一个滚轴,而且是定死在那个位置滚(只对调用方法的对象进行分派),而多分派语言就像下面的老虎机,有好多个对象都可以动态地分派。
多分派语言比较有名的是(Common Lisp),哇,函数式编程语言,看起来就很高大上。
[老虎机图片]()
ps: java,c++中的单分派具体实现在这里没有分析,有兴趣可以看参考资料(),common lisp完全没看过,有时间再看下。有关多分派的内容,请看参考资料()。
###我们来模拟一个双分派
(未完待续)