4

我正在构建一个基于 Joshua 的构建器模式的构建器。我的问题是如何使它成为单例?详细说明我的观点,如果我有以下构建器

public class Widget {
    public static class Builder {
        private String name;

        public Builder( String name) {
            this.name = name;
        }

        public Widget build() {
            Widget result = new Widget(this);
            return result;
        }
        public Builder model( String value ) {
            this.model = value;
            return this;
        }
    }

    private final String name;

    private Widget( Builder b ) {
        this.name = b.name;
    }

    // ... etc. ...
}

我会从另一个类中调用这个构建器,比如 new Widget.Builder().name("abc").build().......

但是如果我只想要这个小部件的一个实例,或者我需要从多个地方访问这个小部件,而不是每次都创建一个新的,该怎么办。理想情况下,我想将实例化限制在 Widget 类中。有什么想法吗?

4

4 回答 4

7

恕我直言,Singleton 和 Builder 模式似乎并没有结合在一起:如果只有一个实例要构建,为什么还需要 builder?

如果您需要重用一个 Builder 对象,因为您想多次构建一个类似的对象,您可以简单地保留对该 Builder 的引用并根据需要多次使用它(因为您将其设为静态):

Widget.Builder builder = new Widget.Builder("abc").model("def");

然后你可以创建几个小部件:

Widget w1 = builder.build();
Widget w2 = builder.build();
...
于 2012-08-01T21:41:04.670 回答
1

如果你真的需要一个单例,Joshua 也有关于在现代 Java 中制作单例的最佳方法的建议。

于 2012-08-01T22:04:16.580 回答
1

如果您需要这样做,并且希望避免污染您的构建器模式,那么添加一个单例来保存构建器的集中实例。

public enum CentralWidgitBuilder{
  INSTANCE; //Effective Java singleton technique

  private final Widget.Builder mBuilder = new Widget.Builder();

  public Widget.Builder getBuilder(){
    return mBuilder;
  }
}

然后从任何地方引用:

CentralWidgitBuilder.INSTANCE.getBuilder().
于 2012-10-10T16:06:13.443 回答
0

如果只有一个构建器对象,那么您可以像这样使用单例模式:

public class Widget {
public static class Builder {
    private static Builder builder;
    private String name;

    public Builder getInstance(String name){
       if (instance==null){
         instance=new Builder(name);
       }
       return instance;
    }

    private Builder( String name) {
        this.name = name;
    }

    public Widget build() {
        Widget result = new Widget(this);
        return result;
    }
    public Builder model( String value ) {
        this.model = value;
        return this;
    }
}

private final String name;

private Widget( Builder b ) {
    this.name = b.name;
}

// ... etc. ...
}

如果您有多个构建器,则可能需要此类中的静态 Map

于 2012-08-01T21:56:53.640 回答