创建可以这样调用的java方法:foo.bar().baz().qux()
我不确定它确切的调用了什么,但我想知道如何创建一个可以在一次调用中调用多个方法的类。例如,使用android类但这并不重要,您可以一次调用该类的所有方法:创建可以这样调用的java方法:foo.bar().baz().qux(),java,android,methods,class-design,Java,Android,Methods,Class Design,我不确定它确切的调用了什么,但我想知道如何创建一个可以在一次调用中调用多个方法的类。例如,使用android类但这并不重要,您可以一次调用该类的所有方法: AlertDialog.Builder().setItem().setTitle().setPositiveButton().setCancelable() ...etc 我认为这可能有效的唯一方法是,如果每个方法都返回this,但这似乎会导致问题。我不知道怎么做,但似乎会 另外,这项技术有名字吗?这项技术被称为,它的工作原理和你想象的完
AlertDialog.Builder().setItem().setTitle().setPositiveButton().setCancelable() ...etc
我认为这可能有效的唯一方法是,如果每个方法都返回this
,但这似乎会导致问题。我不知道怎么做,但似乎会
另外,这项技术有名字吗?这项技术被称为,它的工作原理和你想象的完全一样。您只需让函数返回
此
,而不是无效
,它不会引起问题。返回此
是实现此目的的标准做法
JavaStringBuilder
就是一个例子。()
据说这样的类有一个,其背后的思想是返回对
this
的引用。让我们看一个简单的例子:
class A{
public A setStuffs(){
return this;
}
public A setOtherStuffs(){
return this;
}
}
然后你可以做:
A a = new A().setStuffs().setOtherStuffs();
在使用生成器模式的类中,如
AlertDialog.Builder
,您将看到这一点。但是,我通常在我做的每一个类中都这样做,因为它帮助我保存代码行。这是构建器模式你正在有效地做的是:
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setIcon(android.R.drawable.icon);
builder.setTitle(R.string.title);
builder.setMessage(R.string.message);
//etc.
这称为方法链接,获得这种效果的最简单方法是从每个方法返回对象的当前实例
class MyCoolChainingObject{
public MyCoolChainingObject doSomething(){
//TODO: Stuff
return this;
}
public MyCoolChainingObject doSomethingElse(){
//TODO: Stuff
return this;
}
}
我一直称这种物体为“建筑者” 请注意,好的设计往往在末尾有一个.build()调用,以返回您正在构建的实例
正如您所建议的,所有中间方法调用都返回一个生成器对象。如果生成器对象是可变的,并且方法调用正在修改某些内部生成器状态,则可以是“This”。或者,如果builder对象是不可变的,则每次调用都可能返回一个全新的不可变的builder对象。每个描述方法链接的人都举例说明了实现这一点的完全合理的方法,但仅当您的函数不需要返回某些内容时。如果你想退货怎么办 一个(尽管很糟糕)的解决方案是使用ReturnThis的布尔参数重载所有方法,该参数调用函数,然后返回这个。但是,我绝对推荐使用builder模式来代替此模式 或者!采用按位参数选择要执行的函数的函数!(这是一个糟糕的解决方案!) 还是这样!使用C#并创建一个方法,该方法接受委托(函数指针)的参数数组,并在数组上循环并调用它们(甚至更糟!)
这些是我唯一能想到的选择。如果您不能进行方法链接,那么可以选择builder,或者直接在自己的行中调用它们。或者使用上面三个选项中的一个(但如果你在这一步上,确实会对你的需求的有效性产生疑问)。此外,你也可以使用双括号类实例化hack,使用普通java类,而不是构建总是返回“this”:
AlertDialog.Builder(){{
setItem();
setTitle();
setPositiveButton();
setCancelable();
...etc
}}
这里有一个很好的参考--p.s.如果您正在设计这样的API,我建议您使builder对象不可变。。。。从长远来看,当用户开始传递构建器对象并在不同的线程中使用它们时,它可以节省大量的痛苦。通过将备份数据存储在持久性数据结构的某些类型中,并在末尾添加一个
.create()
:AlertDialog=AlertDialog.Builder(){…}.create()代码>我一直使用双括号实例化hack来测试代码。对于生产代码,我避免使用它。。。因为每次您这样做(您正在子类化)时,它都会创建一个新类。这是我宁愿避免的代价。你是第一个,回答的字符数最少=]
AlertDialog.Builder(){{
setItem();
setTitle();
setPositiveButton();
setCancelable();
...etc
}}