Java 如何将方法标记为强制性? 假设使用Builder模式创建类名,并假定Builder类包含方法“代码>”()/代码>、代码>头()/代码>、代码> ARMs()/,当然 Build()/代码>,并考虑方法>代码>头()/代码>和 Builder()/。
我们希望以某种方式将这些方法标记为强制性的,如果可能的话,使用注释。如果这个类的用户试图构建一个Person实例,但忘记调用其中的任何一个方法,我们希望得到某种警告——来自java编译器,或者来自Eclipse或Maven,我们用来构建我们的项目——它们中的任何一个都可以Java 如何将方法标记为强制性? 假设使用Builder模式创建类名,并假定Builder类包含方法“代码>”()/代码>、代码>头()/代码>、代码> ARMs()/,当然 Build()/代码>,并考虑方法>代码>头()/代码>和 Builder()/。,java,design-patterns,annotations,builder,Java,Design Patterns,Annotations,Builder,我们希望以某种方式将这些方法标记为强制性的,如果可能的话,使用注释。如果这个类的用户试图构建一个Person实例,但忘记调用其中的任何一个方法,我们希望得到某种警告——来自java编译器,或者来自Eclipse或Maven,我们用来构建我们的项目——它们中的任何一个都可以 有可能吗?你建议哪种方法?编译器不行 您可以做的是从build()方法抛出一个运行时异常,该异常表示构建器没有正确初始化(并且有一个在maven测试阶段调用的测试) 但是您也可以让build(…)接受HeadDetails对象
有可能吗?你建议哪种方法?编译器不行 您可以做的是从
build()
方法抛出一个运行时异常,该异常表示构建器没有正确初始化(并且有一个在maven测试阶段调用的测试)
但是您也可以让
build(…)
接受HeadDetails
对象。这样一来,您就不能在不指定强制参数的情况下调用build。也许在build()的内部,您可以检查是否调用了所有必需的方法。BehapsPerson
实例具有一些内部健全性检查,该检查由build()
触发
当然,这会检查运行时行为,而不是您所描述的静态分析。不可能在Person的构造函数中调用这些方法吗?如果build()方法中的body()、head()、arms()确实是必需的,并且在build()方法中返回Person,为什么不在build()方法中调用body()、head()、arms()
[编辑]
简短示例:
public class Builder {
private final String bodyProp;
private final String headProp;
private final String armsProp;
private String hearProps;
public Builder(String bodyProp, String headProp, String armsProp) {
super();
this.bodyProp = bodyProp; // check preconditions here (eg not null)
this.headProp = headProp;
this.armsProp = armsProp;
}
public void addOptionalHair(String hearProps) {
this.hearProps = hearProps;
}
public Person build() {
Person person = new Person();
person.setBody(buildBody());
// ...
return person;
}
private Body buildBody() {
// do something with bodyProp
return new Body();
}
public static class Person {
public void setBody(Body buildBody) {
// ...
}
}
public static class Body {
}
}
我相信正确使用builder模式可以解决您遇到的问题
我将创建类PersonBuilder
,其中包含方法setBody()
和setArms()
以及其他所有可选的参数设置方法。构建器的构造函数将采用所需的参数。然后方法build()
将返回Person
的新实例
public class PersonBuilder
{
private final Head head;
private Body body;
private Arms arms;
public PersonBuilder(Head head)
{
this.head = head;
}
public void setBody(Body body)
{
this.body = body;
}
public void setArms(Arms arms)
{
this.arms = arms;
}
public Person build()
{
return new Person(head, body, arms);
}
}
或者,您可以将Head
参数传递给方法build()
,但我更喜欢将其传递给构造函数。下面是一个使用不同类型强制某些部分的示例(它还使您调用方法的顺序成为强制的):
编辑
OP对这个答案印象深刻,以至于他在一封信中完整地写了出来。这是一个非常巧妙的构建器模式,因此这里值得参考完整的处理方法。除了在非常特殊的情况下,您怀疑在编译时是否可以这样做。不过,在运行时进行这样的检查应该很容易(我一直都是这样做的)。我无法想象除了将强制属性作为参数添加到构建器构造函数或在调用build
时抛出异常之外,还有什么方法可以做到这一点,但我很好奇是否有人有更好的主意。顺便说一句。如果body、head和arms需要一些参数,并且它们也是必需的,那么将它们放在构建器的构造函数中。这些方法需要参数,我必须将这些参数发送到build()方法。据我所知,这与builder模式背道而驰。builder模式的一个想法是,用户可以选择在builder中调用哪些方法。另一种方法是避免使用具有许多参数和许多重载的构造函数(这些重载涵盖了创建此对象的所有可能方法)。恐怕你的建议会破坏这些好处。我们希望保留用户使用他们需要的任何方法创建Person对象的自由,但同时声明会调用一些强制方法,最好是在构建时调用。这是一种非常酷的方法!但这能不能在不强制命令的情况下完成呢。E对于像强制和非强制这样的接口?不,您必须强制执行命令,因为在每个接口中,您都需要一个返回下一步的方法,因此,一旦您在其中一个接口中放入多个方法,您将强制只调用其中一个,以便能够导航到下一步……但您可以向接口中添加不添加属性的方法(例如PersonBuilder.newInstance().head(“head”).doesntHaveABody().arm(“arm”)
package test;
import test.StepOne.StepThree;
import test.StepOne.StepTwo;
import test.StepOne.LastStep;
public class TestBuilder {
public static void main(String[] args) {
String person1 = PersonBuilder.newInstance().head("head").body("body").arm("arm").leg("leg").build();
String person2 = PersonBuilder.newInstance().head("head").body("body").arm("arm").build();
}
}
interface StepOne {
// mandatory
StepTwo head(String head);
interface StepTwo {
// mandatory
StepThree body(String body);
}
interface StepThree {
// mandatory
LastStep arm(String arm);
}
// all methods in this interface are not mandatory
interface LastStep {
LastStep leg(String leg);
String build();
}
}
class PersonBuilder implements StepOne, StepTwo, StepThree, LastStep {
String head;
String body;
String arm;
String leg;
static StepOne newInstance() {
return new PersonBuilder();
}
private PersonBuilder() {
}
public StepTwo head(String head) {
this.head = head;
return this;
}
public LastStep arm(String arm) {
this.arm = arm;
return this;
}
public StepThree body(String body) {
this.body = body;
return this;
}
public LastStep leg(String leg) {
this.leg = leg;
return this;
}
public String build() {
return head + body + arm + leg;
}
}