代码之家  ›  专栏  ›  技术社区  ›  Falmarri

创建可以这样调用的Java方法:Fo.Bar()、BAZ()、Quux()

  •  2
  • Falmarri  · 技术社区  · 14 年前

    我不确定它到底叫什么,但我想知道如何创建一个类,您可以在一个调用中调用多个方法。例如,使用一个Android类,但这并不重要,您可以一次调用所有类的方法:

    
    AlertDialog.Builder().setItem().setTitle().setPositiveButton().setCancelable() ...etc
    

    我唯一能想到的方法是,如果每个方法都返回 this 但这似乎会引起问题。我不知道怎么做,但看起来是这样。

    另外,这个技术有名字吗?

    8 回复  |  直到 13 年前
        1
  •  7
  •   VeeArr    14 年前

    这种技术叫做 method chaining 它的工作原理和你想象的完全一样。您只需返回函数即可 this 而不是 void .

        2
  •  3
  •   chrismarx    14 年前

    此外,与其构建类总是返回“这个”,还可以使用双括号类实例化HACK,使用普通Java类:

    AlertDialog.Builder(){{
      setItem();
      setTitle();
      setPositiveButton();
      setCancelable();
       ...etc
    }}
    

    这是一个很好的参考资料-- http://www.c2.com/cgi/wiki?DoubleBraceInitialization

        3
  •  2
  •   yanchenko    14 年前

    那就是 生成器模式 .
    你有效的做法是:

    AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
    builder.setIcon(android.R.drawable.icon);
    builder.setTitle(R.string.title);
    builder.setMessage(R.string.message);
    //etc.
    
        4
  •  1
  •   Bozho    14 年前

    不会引起问题的。返回 this 是实现这一目标的标准做法。

    爪哇 StringBuilder 就是一个例子。( see source )

    据说这样的班级 fluent interface

        5
  •  1
  •   Cristian    14 年前

    这背后的想法是返回一个参考 this . 让我们来看一个简单的例子:

    class A{
        public A setStuffs(){
            return this;
        }
        public A setOtherStuffs(){
            return this;
        }
    }
    

    然后你可以做:

    A a = new A().setStuffs().setOtherStuffs();
    

    在使用类似于 AlertDialog.Builder . 但是,我通常在我所做的每一个类中都这样做,因为它帮助我保存代码行。

        6
  •  1
  •   mikera    14 年前

    我一直把这种东西叫做“建筑工人”。

    请注意,好的设计往往在末尾有一个.build()调用,以返回正在生成的实例。

    正如您所建议的,所有中间方法调用都返回一个生成器对象。如果构建器对象是可变的,并且方法调用正在修改某些内部构建器状态,则可以是“this”。或者,如果builder对象是不可变的,则调用可能每个都返回一个全新的不可变builder对象。

        7
  •  0
  •   Quintin Robinson    14 年前

    这被称为方法链接,获得这种效果的最简单方法是从每个方法返回对象的当前实例…

    class MyCoolChainingObject{
    
        public MyCoolChainingObject doSomething(){
            //TODO: Stuff
            return this;
        }
    
        public MyCoolChainingObject doSomethingElse(){
            //TODO: Stuff
            return this;
        }  
    }
    

    new MyCoolChainingObject().doSomething().doSomethingElse();
    
        8
  •  0
  •   Dlongnecker    14 年前

    每个描述方法链接的人都举例说明了实现这一点的一个完全合理的方法,但只有当您的函数不需要返回某些东西时。如果你想退货怎么办?

    一个(尽管很差)的解决方案是用一个用于返回的布尔参数重载所有方法。这个参数调用函数,然后返回这个参数。但是,我绝对会推荐构建器模式来代替它。

    或者!接受按位参数的函数,选择要执行的函数!(佐格,这是一个糟糕的解决方案!)

    还是静止!使用c并创建一个方法,该方法接受委托的参数数组(函数指针),并循环该数组并调用所有委托(甚至更糟!)

    这是我唯一能想到的选择。如果你不能做方法链接,去找构建者,或者直接调用它们。或者使用上面三个选项中的一个(但是如果你在这一步中的话,确实会对你的需求的有效性产生疑问)。