有些语言支持函数指针(function pointer)、代理(delegate)、lambda表达式(lambda expression),或者支持类似的机制,允许程序把“调用特殊函数的能力”存储起来并传递这种能力。这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为。
C语言标准库中的qsort函数要求用一个指向comparator函数的指针作为参数,它用这个函数来比较待排序的元素。比较器有两个参数,都是指向元素的指针。通过传递不同的比较器函数,可以获得不同的排列顺序,这是策略模式的一个例子。比较器函数代表一种为元素排序的策略。
什么是策略模式?策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
public class StringLengthComparator { private StringLengthComparator() { } public static final StringLengthComparator INSTANCE = new StringLengthComparator(); public int compare(String str1,String str2){ return str1.length() - str2.length(); } //以上内容用静态单例模式 执行策略 灵活性低。所以设计策略模式时,还要定义一个策略接口。而实现时往往采用匿名内部类来实现。}
为了把StringLengthComparator实例传递给方法,需要适当的参数类型。使用StringLengthComparator并不好,因为客户端将无法传递任何其他的比较策略。相反,我们要定义一个Comparator接口,并修改StringLengthComparator来实现这个接口。换句话说,我们在设计具体的策略类时,还需要定义一个策略接口(strategy interface),如下所示:
public interface Comparator<T> { public int compare(T t1,T t2); }
因为策略接口被用作所有具体策略实例的类型,所以我们并不需要为了导出具体策略,而把具体策略做成公有的。相反,“宿主类(host class)”还可以导出公有的静态域(或者静态工厂方法),其类型为策略接口,具体的策略接口类可以是宿主类的私有嵌套类。下面的例子使用静态成员类,而不是匿名类,以便允许具体的策略类实现第二个接口Serializable:
//已Comparator为策略接口 静态内部类为实现,可以用于多实现 ,如序列化class Host{ private static class StrLenCmp implements Comparator<String>, Serializable{ @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } } public static final Comparator<String> STRING_COMPARATOR_LENGTH= new StrLenCmp();}
简而言之,函数指针的主要用途就是实现策略(strategy)模式。为了在Java中实现这种模式,要声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略模类。当一个具体策略是设计用来重复使用的时候,它的类通常就要被实现为私有的静态成员类,并通过公有的静态final域被导出,其类型为该策略接口。
来源:http://www.icode9.com/content-1-225651.html联系客服