如何在 Builder 设计模式中实现方法的条件可见性?

How to implement conditional visibility of methods in a Builder design pattern?

如何在 Builder 设计模式中更改方法的可见性?

例如我有这个生成器:

public class Builder {

    public Builder a() {
        //
        return this;
    }

    public Builder b() {
        //
        return this;
    }

}

用户可以使用 API 并执行此操作:

new Builder().a().b();
new Builder().a();
new Builder().b();
new Builder().b().a();

我想允许他仅在 a() 被调用时访问方法 b() :

new Builder().a().b();
new Builder().a();

一个简单的示例可以是 SQL 请求生成器。你不应该被允许在 select().

之前调用 when()

如何操作?

如果我没有正确理解你的问题,你可以这样做:

public class Builder {
    
    private boolean aProcessed;
    
    public Builder() {
        this.aProcessed = false;
    }

    public Builder a() {
        //
        aProcessed = true;
        return this;
    }

    public Builder b() throws IllegalAccessException {
        if (!aProcessed) {
            throw new IllegalAccessException();
        }
        //
        return this;
    }

}

两种方法:StepBuilder 模式,提到了 here(感谢 Eritrean)和自定义模式,在后面描述。


StepBuilder

在您的构建器中 class,定义与您的建筑应具有的“步骤”一样多的界面。接口中方法的返回类型 returns 到下一个方法应该可用的类型。

这里b()只能在a()之后调用。

public class Builder {
    /*
     * next available methods are defined by 
     * the returned interface type
     */
    private static interface AStep {
        BStep a();
    }

    private static interface BStep {
       void b();
    }

    private static class Steps implements AStep, BStep {
        BStep a() {
            //
            return this;
        }

        void b() {
           //
           return this;
        }
    }
}

带有抽象的自定义方法class(我称之为:AbstractBuilder

因为我无法使用 StepBuilder 方法定义相同的方法名称,所以我尝试了其他方法。

  • 我定义了一个 main Builder,其中包含第一个可调用方法(可见)、常用方法和 build() 方法(受保护,因为它只能通过其他 class如果需要的话)。

  • 我定义了一个名为 AbstractBuilder 的抽象 class,具有 Builder 类型的属性和一个设置此属性的构造函数。

  • 我定义了多少步骤就有多少构建器。所有这些构建器都扩展了 AbstractBuilder,因此如果需要,可以通过在 Builder 实例上调用它来获得通用方法和结束方法。

看起来像这样:

public class AbstractBuilder {

    protected Builder builder;

    protected AbstractBuilder(Builder builder) {
        this.builder = builder;
    }
}

public class Builder {

    public BStep a() {
        //
        return new BStep(this);
    }

    protected Object build() {
        // 
        return null;
    }
}

public class BStep extends AbstractBuilder {

    protected BStep(Builder builder) {
        super(builder);
    }

    public CStep b() {
        //
        return new CStep(builder);
    }

    public Object build() {
        return builder.build();
    }
}

public class CStep extends AbstractBuilder {

    protected CStep(Builder builder) {
        super(builder);
    }
    
    public BStep and() {
        //
        return new BStep(builder);
    }

    public DStep c() {
        //
        return new DStep(builder);
    }

    public Object build() {
        return builder.build();
    }
}

public class DStep extends AbstractBuilder {

    protected DStep(Builder builder) {
        super(builder);
    }
    
    public CStep and() {
        //
        return new CStep(builder);
    }

    public EStep d() {
        // etc. ... return new EStep(builder);
    }

    public Object build() {
        return builder.build();
    }
}

使用此模式,您可以在每次调用后管理方法的可用性并使用“向后”循环:

Builder builder = new Builder();
builder.a().b().and().a().b().c().and().b().build();