某些语言支持函数指针,允许程序把调用特殊函数的能力存储起来进行传递。这样的机制通常用于允许调用者传入第二个函数,指定自己的行为,这正是策略(Strategy)模式。Java中不支持函数指针,但是可以用对象引用来实现,我们可以专门定义那么一些类,他们的方法执行其他对象的操作。实际上这样的操作本质上是多态:
考虑这么一种情形,一个人(People)类,需要被运输,用的运输工具不一样,
首先定义一个运输接口Transportation:
public interface Transportation{
void transport(People people);
}
定义一个人类People:
public class People{
private int name;
public People(int name){
this.name = name;
}
public int getName(){
return this.name;
}
}
下面定义想要用来进行运输的工具,首先是用车运输:
public class CarTransportation implements Transportation{
@Override
public void transport(People people){
System.out.println("The man "+people.getName()+"is on the car");
}
}
然后定义用船运输:
public class BoatTransportation implements Transportation{
@Override
public void transport(People people){
System.out.println("The man "+people.getName()+"is on the boat");
}
}
最后使用一个测试类:
class Test{
public static void main(String[] args){
People people = new People("Jack");
Transportation car = new CarTransportation();
Transportation boat = new BoatTransportation();
car.tansport(people);//the man Jack is on the car
boat.transport(people);//the man Jack is one the boat
}
}
实际上这就是一个简单的策略模式,事实上,对于CarTransportation和BoatTransportation他们都是无状态的(stateless),他们没有域,因此的所有实例在功能上是相互等价的,因此他们很合适作为一个Singleton(单例模式,详细见这里),可以节省不必要的对象创建开销。
简而言之,函数指针的主要用途就是为了实现策略模式,Java中为了实现这种模式,要声明一个接口来表示这个策略,并且为每个具体策略声明一个实现了该接口的类,当这个具体策略是用来重复使用的时候,它的类通常就被实现为私有的静态成员类,通过公有的静态final域被导出,其类型为该策略接口。比如上面的CarTransportation类和BoatTranportation类,最好写成静态成员类,然后作为一个宿主类的共有静态final域导出,在需要用的地方通过这个域调用:
class Host{
private static class CarTransportation implements Transportation , Serializable{
public void transport(People people){
System.out.println("The man "+people.getName()+"is on the car");
}
}
public static final CAR_TRANSPORTATION = new CarTransportation();
//其他的策略对象
}
然后在需要用的地方直接导出这个共有静态final域进行函数调用:
Host.CAR_TRANSPORTATION.transport(people);
实际上策略模式原理就是面向对象语言的多态特性,为了避免不必要的开销,可以将策略对象作为宿主类的共有静态final域进行导出调用,同时还可以序列化。