美文网首页
用函数对象表示策略

用函数对象表示策略

作者: 没走过的二丁目 | 来源:发表于2018-06-06 15:59 被阅读0次

    有些语言支持函数指针、代理、lambda表达式,或者类似的机制,允许程序把“调用特殊函数的能力”存储起来并传递这种能力。这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为。例如C语言库函数中的qsort函数,通过传递不同的比较器函数,就可以获得各种不同的排列顺序,这正是策略模式的一个例子

    #include<iostream>
    #include <stdlib.h>
    using namespace std;
    int compare(const void *a, const void *b)
    {
        return *(int*)b-*(int*)a;  //从大到小排序
    }
    int main(){
        int a[] = {3,9,8,6,2};
        qsort(a, 5, sizeof(int), compare);
        for(int i= 0;i<5;i++){
            cout<<a[i];//输出98632
        }
    }
    

    Java没有提供函数指针,但是可以用对象指针实现同样的功能。我们可以定义这样一种对象,他的方法执行其他对象上的操作,如果一个类仅仅导出这样的一个方法,他的实例实际上就等同于一个指向该方法的指针,这样的实例被称为函数对象,举个栗子:

    public class StringLengthComparator {  
      
        public int compare(String s1,String s2){  
            return s1.length()-s2.length();  
        }  
      
    }  
    

    为了把StringLengthComparator实例传递给方法,需要适当的参数类型。使用StringLengthComparator并不好,因为客户端将无法传递任何其他的比较策略。相反,通过定义一个Comparator接口,并修改StringLengthComparator来实现这个接口。换句话说,我们在设计具体的策略类时,还需要定义一个策略接口(strategy interface)

    public interface Comparator<T> {  
        public int compare(T t1,T t2);  
    }  
    

    Comparator接口是泛型的,因此它适合作为除字符串之外的其他对象的比较器。
    具体的策略类往往使用匿名类声明,如下代码。

    Arrays.sort(new String[]{"1","123"}, new Comparator<String>() {  
          public int compare(String o1, String o2) {  
               return o1.length()-o2.length();  
          }  
    });
    

    注意:以这种方式使用匿名类时,将会在每次执行调用的时候创建一个新的实例。如果它被重复执行,考虑将函数对象存储到一个私有的静态final域里,并重用它。这样做的另一种好处是,可以为这个函数对象取一个有意义的域名称

    public class Host  {
        private static class StrLenCmp implements Comparator<String> {
    
            @Override
            public int compare(String s, String t1) {
                return s.length()-t1.length();
            }
        }
        public static final Comparator<String> STRATEGY = new StrLenCmp();
    }
    
    

    具体使用

     String[] a = new String[]{"111","1","13"};
            Arrays.sort(a,Host.STRATEGY);
            System.out.print(Arrays.toString(a));//1,13,111
    

    总结:

    函数指针的主要用途就是实现策略(Strategy)模式。

    为了在Java中实现这种模式,要声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类。

    当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略类。

    当一个具体策略是设计用来重复使用的时候,它的类通常就要被实现为私有的静态成员类,并通过公有的静态final域被导出,其类型为该策略接口。

    相关文章

      网友评论

          本文标题:用函数对象表示策略

          本文链接:https://www.haomeiwen.com/subject/potbsftx.html