我正在创建一个检查函数列表的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()来调用方法?这是一个好方法吗?
我想知道是否存在行业标准或设计模式标准来创建这样的界面,以便其他人可以调用它。
非常感谢。
答案 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);
}
}