《JAVA与模式》第24天—访问者模式
访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。
分派的概念
变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type);而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type)。比如
[java]
List list = null;
list = new ArrayList();
List list = null;
list = new ArrayList();
声明了一个变量list,它的静态类型(也叫明显类型)是List,而它的实际类型是ArrayList。
根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派和动态分派。
静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。
动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。
静态分派
Java通过方法重载支持静态分派。用墨子骑马的故事作为例子,墨子可以骑白马或者黑马。墨子与白马、黑马和马的类图如下所示:
在这个系统中,墨子由Mozi类代表
[java]
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:41:24
*
* @类说明 :在这个系统中,墨子由Mozi类代表
*/
public class Mozi {
public void ride(Horse h) {
System.out.println("骑马");
}
public void ride(WhiteHorse wh) {
System.out.println("骑白马");
}
public void ride(BlackHorse bh) {
System.out.println("骑黑马");
}
public static void main(String[] args) {
Horse wh = new WhiteHorse();
Horse bh = new BlackHorse();
Mozi mozi = new Mozi();
mozi.ride(wh);
mozi.ride(bh);
}
}
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:41:24
*
* @类说明 :在这个系统中,墨子由Mozi类代表
*/
public class Mozi {
public void ride(Horse h) {
System.out.println("骑马");
}
public void ride(WhiteHorse wh) {
System.out.println("骑白马");
}
public void ride(BlackHorse bh) {
System.out.println("骑黑马");
}
public static void main(String[] args) {
Horse wh = new WhiteHorse();
Horse bh = new BlackHorse();
Mozi mozi = new Mozi();
mozi.ride(wh);
mozi.ride(bh);
}
}
显然,Mozi类的ride()方法是由三个方法重载而成的。这三个方法分别接受马(Horse)、白马(WhiteHorse)、黑马(BlackHorse)等类型的参数。
那么在运行时,程序会打印出什么结果呢?结果是程序会打印出相同的两行“骑马”。换言之,墨子发现他所骑的都是马。
为什么呢?两次对ride()方法的调用传入的是不同的参数,也就是wh和bh。它们虽然具有不同的真实类型,但是它们的静态类型都是一样的,均是Horse类型。
重载方法的分派是根据静态类型进行的,这个分派过程在编译时期就完成了。
动态分派
Java通过方法的重写支持动态分派。用马吃草的故事作为例子,代码如下所示:
[java]
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:41:46
*
* @类说明 :Java通过方法的重写支持动态分派。用马吃草的故事作为例子
*/
public class Horse {
public void eat() {
System.out.println("马吃草");
}
}
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:41:46
*
* @类说明 :Java通过方法的重写支持动态分派。用马吃草的故事作为例子
*/
public class Horse {
public void eat() {
System.out.println("马吃草");
}
}
[java]
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:43:15
*
* @类说明 :
*/
public class WhiteHorse extends Horse {
@Override
public void eat() {
System.out.println("白马吃草");
}
}
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:43:15
*
* @类说明 :
*/
public class WhiteHorse extends Horse {
@Override
public void eat() {
System.out.println("白马吃草");
}
}
[java]
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:42:08
*
* @类说明 :
*/
public class BlackHorse extends Horse {
@Override
public void eat() {
System.out.println("黑马吃草");
}
}
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:42:08
*
* @类说明 :
*/
public class BlackHorse extends Horse {
@Override
public void eat() {
System.out.println("黑马吃草");
}
}
[java]
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:42:34
*
* @类说明 :
*/
public class Client {
public static void main(String[] args) {
Horse h = new BlackHorse();
h.eat();
}
}
package com.bankht.Visitor;
/**
* @author: 特种兵—AK47
* @创建时间:2012-7-3 上午10:42:34
*
* @类说明 :
*/
public class Client {
public static void main(String[] args) {
Horse h = new BlackHorse();
h.eat();
}
}
运行一下:
[html]
黑马吃草
黑马吃草
变量h的
补充:软件开发 , Java ,