如何将方法标记为强制方法?

发布于 2025-01-01 15:01:57 字数 379 浏览 1 评论 0原文

假设您使用构建器模式创建一个名为 Person 的类,并假设 Builder 类包含方法 body()head()arms() 当然还有 build() 并且您认为方法 head()build() 对于此类的用户来说是必需的。

如果可能的话,我们希望使用注释以某种方式将这些方法标记为强制方法。如果此类的用户尝试构建 Person 实例但忘记调用这些方法中的任何一个,我们希望收到某种警告 - 要么来自 java 编译器,要么来自 Eclipse 或 Maven,我们用它们来构建我们的实例。项目——任何一个都可以。

可以做吗?你会建议哪种方式?

Suppose you create a class names Person using the builder pattern, and suppose the Builder class contains methods body(), head(), arms() and of course build() and you consider methods head() and build() obligatory for the user of this class.

We would like to somehow mark these methods obligatory, if possible using annotations. If a user of this class tries to build a Person instance but forgot to call either of these methods, we would like to get some kind of warning - either from the java compiler, or maybe from Eclipse or Maven, which we use to build our projects - any of them would do.

Is it possible to do? Which way would you suggest?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

静待花开 2025-01-08 15:01:57

下面是一个使用不同类型使某些部分成为强制性的示例(它也使您调用方法的顺序成为强制性的):

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;
    }
}


Edit

OP 对这个答案印象深刻,以至于他在 博客。这是对构建器模式的巧妙采用,值得在这里引用完整的处理方法。

Here is an example with using different types to make some parts mandatory (it also makes the order you call the methods mandatory):

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;
    }
}


Edit

The OP was so impressed with this answer that he wrote it up fully in a blog. It's such a clever take on the builder pattern that a full treatment deserves to be referenced here.

鹿港小镇 2025-01-08 15:01:57

我相信正确使用构建器模式可以解决您遇到的问题。

我将创建类 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(),但我更喜欢将其传递到构造函数中。

I believe the correct use of the builder pattern would solve the issue you're having.

I would create class PersonBuilder which would contain the methods setBody() and setArms() and every other optional parameter setter method. The constructor of the builder would take the required parameters. Then the method build() would return the new instance of 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);
    }
}

Alternatively you could pass the Head parameter to the method build() but I prefer passing it in the constructor instead.

后eg是否自 2025-01-08 15:01:57

编译器没办法。

您可以做的是从构建器未正确初始化的 build() 方法中抛出运行时异常(并在 Maven 测试阶段调用一个测试),

但您也可以使用 build(..) 接受一个 HeadDetails 对象。这样,如果不指定强制参数,就无法调用构建。

No way with the compiler.

You can do is throw a runtime exception from the build() method that the builder is not properly initialized (and have a test that is invoked in the maven test phase)

But you can also have build(..) accept a HeadDetails object. That way tou can't invoke build without specifying the obligatory parameters.

尝蛊 2025-01-08 15:01:57

如果确实是强制性的并且在 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 {
}
}

Why not calling body(), head(), arms() in the build()-Method if it is really mandatory and returning Person in the build() method?

[edit]

Short example:

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 {
}
}
╄→承喏 2025-01-08 15:01:57

也许在 build() 内部,您可以检查是否已调用所有必需的方法。也许 Person 实例有一些由 build() 触发的内部健全性检查。

当然,这会检查运行时行为,并且不是您所描述的静态分析。

Maybe inside of build() you could check if all the required methods have been called. Behaps the Person instance has some internal sanity check which is triggered by build().

Of course this checks runtime behaviour and is no static analysis as you describe it.

青巷忧颜 2025-01-08 15:01:57

无法在 Person 的构造函数中调用这些方法吗?

isn't possible to call these methods in Person's constructor ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文