【问题标题】:How to achieve method chaining in Java?如何在Java中实现方法链?
【发布时间】:2014-02-06 10:49:40
【问题描述】:

我想用Java实现方法链。

我怎样才能实现它?

还请告诉我何时使用它。

public class Dialog {

     public Dialog() {

     }

     public void setTitle(String title) {

         //Logic to set title in dialog
     }

     public void setMessage(String message) {

         //Logic to set message
     }     

     public void setPositiveButton() {

         //Logic to send button
     }
}   

我想创建可以使用的方法链,如下所示:

new Dialog().setTitle("Title1").setMessage("sample message").setPositiveButton();

或喜欢

new Dialog().setTitle("Title1").setMessage("sample message");

或喜欢

new Dialog().setTitle("Title1").setPositiveButton();

【问题讨论】:

  • 喜欢建造者模式?
  • 这通常称为fluencyfluent 编程。
  • 您将为对话框创建一个构建器,而不是为流畅的 api 使用设置器。如果你做了这么多 bean 之类的访问将不再起作用,因为框架限制 setter 返回 void。如果您不喜欢编写所有样板文件,请查看 project lombok。
  • Lombok 实验性注释,带有fluent=true:projectlombok.org/features/experimental/Accessors

标签: java methods chaining


【解决方案1】:

如果您使用的是 lombok,您可以在 lombok.config 中使用参数:

lombok.accessors.chain = true

或者对于特定的数据类你可以声明@Accessors(chain = true)注解:

import lombok.experimental.Accessors;

@Accessors(chain = true)
@Data
public class DataType {

    private int value;

    // will generate setter:
    public DataType setValue(int value) {
        this.value = value;
        return this;
    }

}

【讨论】:

    【解决方案2】:

    只需添加一个静态构建器方法,然后创建另一组 setter 方法。 例如

    class Model {
       private Object FieldA;
    
       private Object FieldB;
    
       public static Model create() {
           return new Model();
       }
    
       public Model withFieldA(Object value) {
           setFieldA(value);
           return this;
       }
    
       public Model withFieldB(Object value) {
           setFieldB(value);
           return this;
       }
    }
    

    ...

    并像使用它

     Model m = Model.create().withFieldA("AAAA").withFieldB(1234);
    

    【讨论】:

      【解决方案3】:

      让你的方法返回this,比如:

      public Dialog setMessage(String message)
      {
          //logic to set message
          return this;
      }
      

      这样,每次调用其中一个方法后,您都会返回相同的对象,以便您可以调用另一个方法。

      当您想在对象上调用一系列方法时,此技术很有用:它减少了实现该目标所需的代码量,并允许您在方法链之后有一个返回值。

      减少显示对话框所需代码量的示例如下:

      // Your Dialog has a method show() 
      // You could show a dialog like this:
      new Dialog().setMessage("some message").setTitle("some title")).show();
      

      使用单个返回值的示例如下:

      // In another class, you have a method showDialog(Dialog)
      // Thus you can do:
      showDialog(new Dialog().setMessage("some message").setTitle("some title"));
      

      丹尼斯在对您的问题的评论中提到的使用构建器模式的示例:

      new DialogBuilder().setMessage("some message").setTitle("some title").build().show();
      

      构建器模式允许您在构建对象之前为类的新实例设置所有参数(考虑具有 final 字段的类或在构建后设置值比设置值更昂贵的对象当它被构建时)。

      在上面的示例中:setMessage(String)setTitle(String) 属于 DialogBuilder 类并返回调用它们的 DialogBuilder 的相同实例; build() 方法属于DialogBuilder 类,但返回一个Dialog 对象 show() 方法属于Dialog 类。

      额外

      这可能与您的问题无关,但可能会对您和遇到此问题的其他人有所帮助。

      这适用于大多数用例:所有不涉及继承的用例和一些涉及继承的特殊情况,当派生类不添加您想要链接在一起的新方法时您对使用(不强制转换)方法链的结果作为派生对象不感兴趣。

      如果您想为派生类的对象提供方法链,而派生类的基类中没有方法,或者您希望方法链将对象作为派生类的引用返回,您可以查看在this question 的答案中。

      【讨论】:

      • 我添加了最后使用的示例,因为我错过了您的部分问题。请注意,这些并不是方法链接和/或构建器模式的唯一用途:与大多数编码模式、算法和技术一样,只要有一点创造力,就可以找到旧模式(算法、技术)的新用途 :)
      • 更改设置行为不是一个好习惯,因为某些框架不期望 setter 方法有任何返回。例如,如果您的模型中的设置器将返回一些值,您将在 Cassandra Java 驱动程序中遇到错误。
      【解决方案4】:

      减少显示对话框所需代码量的示例如下:

      package com.rsa.arraytesting;
      
      public class ExampleJavaArray {
      
      String age;
      String name;
      
      public ExampleJavaArray getAge() {
          this.age = "25";
          return this;
      }
      
      public ExampleJavaArray setName(String name) {
          this.name = name;
          return this;
      }
      public void displayValue() {
          System.out.println("Name:" + name + "\n\n" + "Age:" + age);
      }
      }
      

      另一个类

      package com.rsa.arraytesting;
      
      public class MethodChaining {
      
      public static void main(String[] args) {
      
          ExampleJavaArray mExampleJavaArray = new ExampleJavaArray();
      
          mExampleJavaArray.setName("chandru").getAge().displayValue();
      
      }
      
      }
      

      【讨论】:

      • 包 com.rsa.arraytesting;公共类 MethodChaining { public static void main(String[] args) { ExampleJavaArray mExampleJavaArray = new ExampleJavaArray(); mExampleJavaArray.setName("chandru").getAge().displayValue(); } }
      猜你喜欢
      • 2020-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      相关资源
      最近更新 更多