如何强制实施 API Java

How to force an implementation for an API Java

我们有关于 API 设计的问题。它在我的头上钻了一个洞,我想不通。

举例来说,我有一个带有一种方法的接口,用于读取文件,但您需要传递某种凭据,所以这里的对象实际上可以是任何 pojo。

public interface Reader(){
     public void read(String identifier, Object credentials);
}

问题是如果开发人员扩展它来实现凭据,我该如何强制他们确保它是有效的凭据而不是绕过它。以下是我建议的解决方案:

public boolean authenticate(Object credentials);

或者,它可能是这样的

 public Object authenticate(Object credentials);

我也试过这种方式,所以它给了一个默认的认证

public interface Auth {
    default boolean authenticate() {
        //do real authentication
        return true;
    }
}

以及我将传递给 Reader 接口的响应,他们回来说我说开发人员也可以随时忽略它,只说 return true。而这一切都是错误的。

他们暗示答案与Abstract classes有关,但我在想如果它是一个抽象的class,是不是意味着如果我扩展了就不意味着我仍然可以重写这个方法吗?然后说 return true 还在吗?

abstract class Auth {
    public boolean authenticate(Object o) {
        //some real authentication
        return boolean ;
    }
}
//developer implementation
class extends AuthImpl extends Auth{
        public boolean authenticate(Object o){
            return true;
        }
}

这是一个小组讨论,他们都同意有一种方法可以让开发人员不能只 return 对摘要进行 true 处理。我在这里错过了什么?我如何强制开发人员正确实施实际身份验证,而不仅仅是 returning true?请帮助似乎无法解决这个问题

我认为他们希望看到以下合同模式:

public abstract class Reader(){

     // Requirement to implement:
     protected abstract void authenticate(Object credentials);

     // Requirement to implement:
     protected abstract void actuallyRead(BufferedReader in, String identifier,
         Object credentials) throws IOException;

     //  Service provided:
     public final void read(String identifier, Object credentials) {
         ... using authenticate and actuallyRead ...
     }
}

客户端开发人员 仅具有 API 的 read 功能。但是 实现者 必须提供功能 (authenticate, actuallyRead)。用作 API 创建者 指定的。

注意 actuallyRead 可以传递(提供)和 return(需要)额外信息。

如果你想强制实施,你必须有一个 class,抽象与否。当然 authenticate 会变成 final 所以它不能被覆盖(当然,如果你是开发者,没有什么能阻止你把它变成非最终的,所以它变得有点学术化了真的能保证安全)。

一种方法是只将外部的 Reader 实现作为参数,这样开发人员可以自由实现读取,但系统的其余部分总是到处使用 AuthReader (这会直接依赖于身份验证,绕过它要困难得多,因为它需要更改所有使用它的地方)。这允许读取的灵活性,但身份验证的安全性。

像这样

public final class AuthReader implements Reader {
    private Reader reader;
    private Object credentials;
    public AuthReader(Reader reader, Object credentials) {
        this.reader = reader;
        this.credentials = Objects.requireNonNull(credentials);
    }

    private boolean isAuthenticated() {
        ... // authenticate credentials
    }

    public String readString() {
        if(!isAuthenticated())
            throw new SecurityException();
        return reader.readString();
    }
}

在编译时确保凭据

假设您只允许使用有效凭据实例化 Authorized 实例。

假设你有这个:

public final class Authorized {
    private final Object credentials;

    public abstract class Reader {
    }

    public Authorized(Object credentials) {
        if (credentials == null) {
            Objects.requireNonNull(credentials, "Missing credentials");
        }
        this.credentials = credentials;
    }
}

这样你可以从 Reader 扩展,但是你不能从 Reader 实例化一个超类,而 没有 [=] 的实例12=].

示例:

public class MyReader extends Authorized.Reader {
    public MyReader() {
           // YOU MUST CALL .super() HERE ON A 
           // INSTANCE OF Authroized or you can not compile.
    }
}
  1. 在 MyReader 的默认构造函数中,您必须使用 Authroized 的实例,例如 new Authorized("").super().
  2. 不能继承Authroized重写构造函数
  3. 如果没有 Authroized.
  4. 的实例,则无法创建 MyReader 的实例

经过深思熟虑并根据此处的所有答案,我认为这就是他们的意思。感谢@Kayaman 的回答引导了正确的方向。

通过abstract就是这样,因为你强加了Reader有1个参数constructor他不能实例化它,他被迫放一个super 调用他的实现。

abstract class Reader {
    protected Object authentication;
    ReaderImpl(Object authentication) throws Exception{
        if(null == authentication){
            throw new Exception();
        }else{
            this.authentication = authentication;
        }
    }
    public void reader(String x, Object authentication) {
        System.out.println("Reader Implemented");
    }

}

class DevReader extends Reader{
    public DevReader(Object authentication) throws Exception{
        super(authentication);
    }
    @Override
    public void reader(String x, Object authentication) {
        System.out.println("Dev Implemented");
    }
}