Command dispatching
命令调度
In C and C++, programmers often use a set of global functions and function pointers to represent a series of commands or operations and then dispatch to them via a table. For example:
在C/C++里,程序员经常会定义一些全局函数和函数指针来描述一系列命令或操作,然后通过列表来调度他们.一个例子:
#include <stdio.h>
//定义了两个函数
void func1() {printf("func1/n");}
void func2() {printf("func2/n");}
//定义函数指针类型
typedef void (*fp)(void);
//定义了两个函数指针,分别指向前边定义的两个函数
fp funcs[] = {&func1, &func2, 0};
int main()
{
int i = 0;
//根据i的情况来调用不同的函数
while (funcs[i])
funcs[i++]();
return 0;
}
Java, though, does things differently. It doesn't use pointers and doesn't have global functions. Instead, Java uses a technique of creating and referencing object instances through which the objects call a method known to be implemented by an object of a given type.
尽管在Java没有全局函数和没有函数指针,Java是通过不同的方式实现的.取代的办法是Java利用对象的引用来实现这种功能.
How does the technique work in practice? Consider this example:
这种技术是如何实现的,可以参考以下的例子:
//定义一个接口
interface Action {
public void doit();
}
//定义了类func1,这个类实现了Action接口
class func1 implements Action {
public void doit() {System.out.println("func1");}
}
//定义了类func2,这个类也实现了Action接口
class func2 implements Action {
public void doit() {System.out.println("func2");}
}
//通过动态调用
public class call {
private static Action alist[] = {
new func1(),
new func2()
};
public static void main(String args[])
{
for (int i = 0; i < alist.length; i++)
alist[i].doit();
}
}
In this example, an interface Action is defined, and any class that implements the interface must define a method doit (this notion, by the way, is basic to the meaning of interfaces). Objects of the class can be referred to with a reference to the implemented interface name type, so that a reference of type Action can refer to an object of a class that implements Action.
再这个例子中,定义了一个Action接口,接口定义了一个doIt方法和两个实现了这个接口的类func1和func2.对于实现了Action接口的实例可以通过Action的类型的引用来引用.于是这个Action的引用就可以指向实现了这个接口的类的实例.
In C++ programming Action would be a base class, with func1 and func2 being derived classes, and object manipulation would be performed via a base class pointer. With Java, an Action reference supports a similar manipulation, although Action is not a superclass of func1 and func2.
在C++语言里,Action接口可以转换成一个基类,func1和func2则可以成为子类,对于子类的实例可以用基类变量保存.在java里面,虽然Action接口并不是具体类的父类,但是通过基类引用引用子类的机制还是一样的.
The Java technique given here sometimes goes by the name "method wrappers," and is quite different from the C/C++ approach. There are some tradeoffs, of course, as to which approach works the best in a given situation.
这种Java技术通常被称作"方法包装",这点有很大区别于C++.但是至于哪种方法会更合适就要看商业运用了.
A second example
第二个例子
Another example of the method wrappers technique is used fairly often in the Abstract Windowing Toolkit (AWT). Consider the following:
关于方法包装的一个例子,这种技术通常在AWT中利用.
参看一下代码:
import java.awt.*;
import java.awt.event.*;
//一个按钮监听器,实现了ActionListener接口
public class buttonlistener implements ActionListener {
//实现了actionPerformed方法
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
public static void main(String args[])
{
Frame f = new Frame("testing");
Button b = new Button("OK");
b.addActionListener(new buttonlistener());
f.add(b);
f.pack();
f.setVisible(true);
}
}
The example creates a frame and adds an OK button to it. When the button is selected, the program terminates. An action listener is added to the button. The action listener is guaranteed to implement a method actionPerformed, because an instance of buttonlistener implements the ActionListener interface. Selecting the button results in a call to the action listener for the button.
这个例子中,新建了一个窗口,窗口只有一个OK按钮.当按钮按下是,程序结束.对于OK按钮,我们给他添加了一个监听器,监听器实现了actionPerformed方法,按下按钮的结果就会调用这个按钮的监听器.
Finally, the listeners concept is extremely important in the AWT. The underlying basis of listeners involves implementing specified interfaces and thereby guaranteeing that a listener will be able to respond to a particular known method invocation on it.
最后强调一点,就是监听器的概念在AWT中非常的重要.