在Java中创建API库的方法是什么?

时间:2015-01-17 02:19:00

标签: java api interface static-methods

我正在创建一个检查函数列表的API。有一个对象作为参数传入以进行检查。

对象如下:

public class People{

    private String name;
    private String address;
    private int age;
    private String job;

    public getter() ...
    public setter() ...

}

我创建了一个包含检查函数列表的类,以确保提供的信息是否有效。例如:

public class checkingFunctions {

public static boolean checkName(People ppl){

     perform the name checking function;

}

public static boolean checkAge(People ppl){

     perform the age checking function;

}

}

我知道上面的方式可以作为API使用,以便其他人可以调用checkingFunctions.checkName(ppl)。但这是构建将作为jar文件暴露给其他人的API的正确方法吗?我正在考虑创建一个checkFunctions接口,如下所示:

   public interface ICheckingFunctions {

        boolean checkName(People);

        boolean checkAge(People);

}

让checkFunctions类实现它,比如

public class checkingFunctions implements ICheckingFunctions {

}

因为如果它覆盖了超类方法,则checkName和checkAge不能声明为静态,因此不会编译它。

或者我应该只使用接口并让它实现接口,但是从所有检查方法中删除静态。那么,如果其他人想要使用我的API,他们只是实例化接口,并使用instance.checkName()来调用方法?这是一个好方法吗?

我想知道是否存在行业标准或设计模式标准来创建这样的界面,以便其他人可以调用它。

非常感谢。

1 个答案:

答案 0 :(得分:1)

如何设计这样的API在很大程度上取决于您的API的使用方式。

例如,如果结果是,您的People类最好被实现为最终类,并且您希望以相同的一致方式确保它始终为checked,然后提供许多公共静态check...方法当然是一种合理的方法。

另一方面,如果您事先不知道应该如何检查People课程,那么我考虑提供一个ICheckingFunctions界面来声明必要check...}方法。但是如果你走这条路,你可能还需要为用户提供一种方法来改变实际使用的ICheckingFunctions实现。

您还应该考虑,虽然使用接口肯定更加灵活和可扩展,但维护工作也更多,并且还可能带来安全风险 - 例如如果您允许用户更改已使用的ICheckingFunction,则您无法再控制People类的检查方式。

使用接口实现此类API的一种可能方法是允许用户在您的类中注册/取消注册已使用的ICheckingFunction非常天真的实现可能如下所示:

public final class CheckingFunctions {
    private static ICheckingFunctions checkFunction;

    public static void registerCheckFunction(ICheckingFunctions checkFunction) {
        CheckingFunctions.checkFunction = checkFunction;
    }

    public static boolean checkName(People ppl){
        return checkFunction.checkName(ppl);
    }

    public static boolean checkAge(People ppl){
        return checkFunction.checkAge(ppl);
    }
}

这当然只是一个很小的例子。在实际的API中,您必须决定很多其他细节。例如:

  • 是否只有一个ICheckingFunctions实例可用?如果可能有更多注册ICheckingFunctions - 您如何选择使用这些功能?
  • 谁可以注册/取消注册ICheckingFunctions实例?
  • 可以从不同的线程调用ICheckingFunctions吗?

您还必须考虑将在哪种环境中使用您的API。例如,如果您希望在OSGI环境中支持使用您的API,那么您可以例如提供您的ICheckingFunctions作为OSGI服务。

最后但并非最不重要的我会考虑以下内容:您的用户可以继承People类吗?如果是,那么将ICheckingFunctions接口设为通用可能是个好主意,并允许为不同类注册实现。这又是一个非常天真的这种方法的例子:

public final class CheckingFunctions {
    public interface ICheckingFunctions<T extends People> {
        boolean checkName(T p);    
        boolean checkAge(T p);
    }

    private static Map<Class<?>,ICheckingFunctions<?>> checkFunctions = new ConcurrentHashMap<>();

    public static <T extends People> void registerCheckFunction(ICheckingFunctions<T> checkFunction, Class<T> c) {
        checkFunctions.put(c, checkFunction);
    }

    private static <T extends People> ICheckingFunctions<T> getRegisteredCheckFunction(Class<T> c){
        ICheckingFunctions<T> checkFunction = (ICheckingFunctions<T>) checkFunctions.get(c);
        if (checkFunction == null) {
            // provide some reasonable default?
            throw new IllegalStateException();
        }
        return checkFunction;
    }

    public static <T extends People> boolean checkName(T ppl, Class<T> c){
        return getRegisteredCheckFunction(c).checkName(ppl);
    }

    public static <T extends People> boolean checkAge(T ppl, Class<T> c){
        return getRegisteredCheckFunction(c).checkAge(ppl);
    }
}