java - 具有 getter 和 setter 的对象的 Fluent Interface (Java)

标签 java fluent-interface

我阅读并喜欢这篇文章 http://blog.jooq.org/2012/01/05/the-java-fluent-api-designer-crash-course/来自 Lukas Eder,我想为一个类创建一个 Fluent Interface。

该类有四个允许设置对象属性的函数(“words”fill1 到 fill4)和四个获取这些属性的函数(“words”get1 到 get4),但前提是已设置所需的属性:

首先,我必须填写基本设置 (fill1)。之后,我要么能够获得其中一些设置(get1 到 get3),它们是字符串。或者我可以填写更多信息(fill2 到 fill4)。但只有在 every fill2 到 fill4 被调用至少一次之后,才能调用最后的 get4。我该怎么做?

第一张图(状态是黑点)显示了我想做的事情,但是正如你所看到的?标记不清楚的部分,因为如果保留在第一个图中,即使只调用了 fill2 到 fill4 中的一个,也可以调用 get4。

第二张图将强制调用每个 fill2 到 fill4,但如果我想更改,则会强制执行并限制顺序,例如fill3,我还必须重置 fill2 和 fill4。

最后一张图可以满足我的要求,但它有 13 个状态!现在,如果我想象我会再添加一个属性到 fill2 到 fill4 组,状态的数量会爆炸得更多。

enter image description here

编辑:此外,在进一步考虑之后,我注意到我这样做的方式(见下文)甚至无法实现最后一个图表,因为在 fill2 之后被调用时,我们可能处于不同的状态 - 取决于之前发生的事情。

我能/应该做什么?

编辑:我实现我的流畅界面有点像外观(如果我的设计模式正确的话)。我的意思是:我几乎没有触及实际的类 - 返回 this(如在方法链接中),但是将各自的状态接口(interface)作为方法签名中的返回值。状态由嵌套接口(interface)表示。示例:

public class MyClass implements MyInterface.Empty, MyInterface.Full {

    String stuff;

    private MyClass(){};

    public static MyInterface.Empty manufactureNewInstance(){
        return new MyClass();
    }

    public MyInterface.Full fillStuff(String stuff){
        this.stuff = stuff;
        return this;
    }

    public String getStuff(){
        return stuff;
    }

}

public interface MyInterface {

    public interface Empty {
        public MyInterface.Full fillStuff();
    }

    public interface Full {
        public String getStuff();
    }

}

public class MyMain {

    pulic static void main(String[] args) {

        // For explaination:
        MyClass.Empty myclassEmpty = MyClass.manufactureNewInstance();
        MyClass.Full myclassFull = myclassEmpty.fillStuff("Hello World 1!");
        String result1 = myclassEmpty.getStuff();

        // As fluent chaining:
        String result2 = MyClass.manufactureNewInstance()
            .fillStuff("Hello World 2!")
            .getStuff();

    }

}

最佳答案

Java 中的 Fluent 接口(interface) API 在一定程度上受到限制,因为您需要用不同的类型表示每个 API 状态。这是因为 Java 类型是将一组 API 约束传递给 Java 编译器以进行验证的唯一方式。

显然,在创建流畅的 API 时,这是一个不幸的限制。要克服此限制,您需要:

  1. 通过例如接口(interface)手动实现所有 API 状态。如果您的代码不太可能更改,例如,这可能是一个可行的解决方案。在一个范围相当有限、不应该存在太久的项目中。然后,单个支持类可以实现代表每个API 状态 的所有接口(interface)。只要用户不使用反射或类型转换,编译器就会验证方法是否按合法顺序调用。

  2. 自动生成代码。这是一种更雄心勃勃的方法,但如果您的 API 状态组合如您所说的那样“爆炸”,它可以为您节省大量的输入和重构工作。我写了一个名为 Byte Buddy 的代码生成库我知道用户使用该库为流畅的 API 创建接口(interface)。 (不幸的是,我在这件事上联系的两个用户没有开源他们的代码。)如果你更想创建 Java 源代码而不是 Java 字节代码,那么 Java poet可能是您的替代方案,我也看到了这个用例。

  3. 简化您的 API,使其仅验证最常见的错误,同时在运行时通过异常检查不太常见的错误。这通常是一个可行的解决方案,因为它使 API 更易于使用。

关于java - 具有 getter 和 setter 的对象的 Fluent Interface (Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32740396/

相关文章:

java - 如何将记事本/电子表格中的数据集导入 Matlab GUI

api - 如何访问 CaSTLe Windsor 的 Fluent Interfaces API?

entity-framework - EF 6 Fluent Configuration - 与父级递归嵌套对象 - TPH

java - 匿名类隐藏对局部变量的引用

在 Eclipse 中单击同一按钮上的 Java 线程启动-停止-启动

java - LinkedTransferQueue 是阻塞队列还是非阻塞队列?

asp.net-mvc - 如何在 ASP.NET MVC 中实现流利的 api?

java - BaseFoo 不能用不同的参数 : <T, X.Bar<T>> 和 <T,X.Foo<T>> 继承

javax.net.ssl.SSLPeerUnverifiedException : No peer certificate when downloading website content android