Java 如何为多接口继承启用类似生成器的模式?

Java 如何为多接口继承启用类似生成器的模式?,java,builder,Java,Builder,首先,让我们定义我们的接口: 可转换的公共接口{ R寄存器转换(函数转换); T过程(T实体); } 公共接口HttpService{ T执行(URL); } 如界面Transformable所示,我们可以创建一个简单的构建器模式来注册转换并在一行中执行所有转换,例如: newdefaultTransformableImpl(){} .registerTransformation(编号->编号*2) .registerTransformation(编号->编号-1) .registerTra

首先,让我们定义我们的接口:

可转换的公共接口{
R寄存器转换(函数转换);
T过程(T实体);
}
公共接口HttpService{
T执行(URL);
}
如界面
Transformable
所示,我们可以创建一个简单的构建器模式来注册转换并在一行中执行所有转换,例如:

newdefaultTransformableImpl(){}
.registerTransformation(编号->编号*2)
.registerTransformation(编号->编号-1)
.registerTransformation(编号->编号*编号)
.过程(109845)
好了,现在我们准备创建
HttpService
的实现。这样做的目的是提供修改标头、HTTP方法。。。在将请求实际发送到服务器之前,无需为
org.jsoup.connection
接口指定方法适配器,即可创建连接实例的:

import java.util.function.function;
导入java.util.List;
导入java.net.URL;
导入org.jsoup.Connection;
导入org.jsoup.helper.HttpConnection;
导入org.jsoup.nodes.Document;
导入lombok.skillythrows;
公共类JsoupHttpService实现HttpService,可转换{
private final List fns=new LinkedList();
@重写公共R寄存器转换(函数转换){
this.fns.add(转换);
返回(R)本文件;
}
@覆盖公共连接进程(连接){
返回fns.stream().reduce(Function.identity(),Function::and then).apply(connection);
}
@鬼鬼祟祟
@重写公共文档执行(URL){
返回此.process(HttpConnection.connect(url)).execute().parse();
}
}
这只是对实际实现的简化,只关注问题的必要部分,这可以通过尝试将
JsoupHttpService
与方法链接结合使用来看出:

公共文档doSomething(){
返回新的JsoupHttpService(){}
.registerTransformation(连接->连接.method(连接.method.GET))
.registerTransformation(连接->连接.userAgent(“假用户代理”))
.执行(”https://www.google.com")
.parse();
}
如果您在IDE中尝试此方法,它会说一些接近于无法解析“Transformable”中的方法“execute”。。。所以我想知道你们是否知道我如何在不修改两个接口的情况下解决这个问题。
我唯一的选择是创建另一个扩展
HttpService
的接口,并尝试在其内部调整
Transformable
中定义的方法吗?

问题是
registerTransformation
返回一个
Transformable
。可转换的
不是
HttpService

您可以通过以下方式实现您想要的:

JsoupHttpService service = new JsoupHttpService();
service.registerTransformation(connection -> connection.method(Connection.Method.GET));
service.registerTransformation(connection -> connection.userAgent("fake user-agent"));
service.execute();

可转换接口的作者似乎没有正确理解何时适合使用
extends
。对
(R)
的未经检查的强制转换应该是这方面的线索。

我认为几乎任何使用多重继承的方法,即使是使用接口,都是一个坏主意。此外,将泛型与类型继承混合在一起会导致噩梦般的混乱——看看围绕
Comparable
Enum
的奇怪结构

显然,这不会阻止我修改代码

如果您有一个类型参数仅用于返回类型的方法,则该方法的选项有:return
null
、抛出异常、执行堆类型污染、不返回或更糟

对于构建器的这类问题,解决方案是使用递归定义的类型参数混乱地参数化构建器类型,并可能添加一个抽象的“get this”方法(如果
Transformable
是抽象的,因此可能有字段,则更常见)

public interface Transformable<THIS extends Transformable<THIS, T>, T> {
    THIS registerTransformation(Function<T, T> transformation);
    T process(T entity);
}

public class JsoupHttpService implements HttpService<Document>, Transformable<Connection> {
    private final List<Function<Connection, Connection>> fns = new LinkedList<>();

    @Override public JsoupHttpService registerTransformation(Function<Connection, Connection> transformation) {
        this.fns.add(transformation);
        return this;
    }
然后在
JsoupHttpService
中:

    @Override public JsoupHttpService getThis() {
        return this;
    }

你是对的,但这对方法链接没有帮助。是的,不安全的强制转换有点烦人…我怎么解决它?我觉得扩展是必要的,以便能够使用接口实现具体的方法和属性。你问如何在不更改这些接口的情况下解决它。这是如何工作的。为什么你这么担心你是否可以链接它们吗?我理解你的担心…它允许使用其他有趣的模式。确实有点混乱,但我尝试过,它出人意料地有效。谢谢!(我不确定是否需要
getThis()
方法)
    @Override public JsoupHttpService getThis() {
        return this;
    }