【问题标题】:What is the way to create API Library in Java用Java创建API库的方法是什么
【发布时间】:2015-01-17 02:19:00
【问题描述】:

我正在创建一个检查函数列表的 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 工作,以便其他人可以调用 checksFunctions.checkName(ppl)。但这是构建将作为 jar 文件公开给其他人的 API 的正确方法吗?我正在考虑创建一个如下的检查函数接口:

   public interface ICheckingFunctions {

        boolean checkName(People);

        boolean checkAge(People);

}

并让checkingFunctions类来实现它,就像

public class checkingFunctions implements ICheckingFunctions {

}

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

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

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

非常感谢。

【问题讨论】:

  • @Devs 不是真的,这个问题是关于如何将代码打包为 API,这个问题更多的是关于一个好的 API 是什么样的。
  • setName() 方法可以检查名称,也可以将checkName() 方法添加到 People 类中。会有帮助吗?
  • 谢谢,或者我应该只使用接口并让它实现接口,但从所有检查方法中删除静态。那么,如果其他人想使用我的 API,他们只需实例化接口,并使用 instance.checkName() 调用方法?这是个好方法吗?
  • 对象本身不应该自我验证吗?这就是 OO 的意义所在。过程语言将具有验证其他“结构”的功能,但 OO 语言应该专注于自包含的工作单元 - 恕我直言。并不是说您不会拥有不会进行额外检查的业务逻辑

标签: java api interface static-methods


【解决方案1】:

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

例如,如果事实证明,您的 People 类最好作为最终类实现,并且您想确保它始终以相同的一致方式为 checked,然后提供一些公共static 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);
    }
}

【讨论】:

  • 非常感谢您的详尽和有用的反馈。我实际上知道将如何检查人员类。但只是人员类可能会更改,我还需要对我的检查功能进行一些更改。但是,我知道人员类将如何改变以及我应该如何改变我的检查功能。我的检查功能的使用者不需要更改现有检查功能(如检查名称)的代码,他们需要为新添加的检查功能(如检查地址)添加新的函数调用。是的,我应该让 ppl 类成为最终的,因为我只是读而不写
  • 如上面评论的情况,我还应该使用这种注册方式来构建这个API吗?或静态方法。让所有的检查功能成为公共(非静态)方法,并定义一个包含所有这些检查功能的接口怎么样。调用者只需要实例化这个接口(例如,checkingfunctions),然后像这样调用函数:checkingfunctions.checkName(ppl);这也可行吗?对于这个接口和包含静态方法的类,推荐哪一个?谢谢
  • 如果只有您一个人需要更改检查功能,而您的用户永远不应该更改它们,那么我肯定会为这些功能使用公共静态方法。但如果可能的话,我会考虑添加一个默认检查方法而不是多个。例如。只是public static check(People)。然后,此默认方法可以酌情调用更具体的函数,如checkNamecheckAddress 等。这样,您的用户可能不需要在每次向代码添加新的检查功能时更改他们的代码。
  • 如果你知道只有一个类可以扩展这个接口,我不会提供公共 api 的接口......
  • 谢谢,是的,我就是这么做的。我创建了一个方法调用 checkPeople,包括所有相关的方法,如 checkName、checkAge。但来电者告诉我,他们还需要单独访问某些特定方法,例如 checkName 。因此,它需要向他们开放所有的检查方法。我可以使用静态方法。顺便说一句,我是这项检查服务的唯一所有者,没有其他人可以更改它。
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 2022-06-28
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多