Java API中的Builder模式示例?

时间:2010-01-30 19:46:05

标签: java design-patterns builder

Joshua Bloch的 Effective Java 描述了一种Builder模式,可用于构建具有多个可选定制参数的对象。他为Builder函数建议的命名约定,“模拟在Ada和Python中找到的命名可选参数”,似乎不符合Java的标准命名约定。 Java函数往往依赖于使用动词来启动函数,然后依靠基于名词的短语来描述它的作用。 Builder类只有该函数定义的变量名称。

Java标准库中是否有使用Builder模式的API?我想在继续使用之前,将本书中的建议与核心Java库集中的实际实现进行比较。

7 个答案:

答案 0 :(得分:17)

我不确定核心JDK,但在Guava中可以找到很好的例子。 MapMaker可能是我能想到的最好的例子。例如,来自docs:

ConcurrentMap<Key, Graph> graphs = new MapMaker()
    .concurrencyLevel(32)
    .softKeys()
    .weakValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeComputingMap(
        new Function<Key, Graph>() {
          public Graph apply(Key key) {
            return createExpensiveGraph(key);
          }
        });

是的,这种事情可能与“标准”Java命名无关,但它也可以非常易读。

对于你没有返回“this”而是一个新对象(通常使用不可变类型)的情况,我喜欢“with”前缀 - Joda Time广泛使用该模式。这不是构建器模式,而是替代和相关的构造形式。

答案 1 :(得分:5)

Locale类有一个Builder模式的例子。 https://docs.oracle.com/javase/7/docs/api/java/util/Locale.Builder.html

用法:

Locale locale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();

答案 2 :(得分:4)

有效的java书籍中唯一最准确的构建器是StringBuilder。 我从示例中看到的唯一区别是此构建器不是String的内部类。

所有方法都将构建器对象返回到链。而toString()方法是build()方法。

答案 3 :(得分:2)

SAXParser似乎是一个很好的例子:

  • SAXParser - 导演
  • ContentHandler - 构建器

SAXParser的典型用法与Builder相同:

// Create Director
SAXParser parser = new org.apache.xerces.parsers.SAXParser();  
// Create Concrete Builder (our own class)
IdentingContentHandler handler = new IndentingContentHandler();
// Set Buidler to Director
parser.setContentHandler(handler);
// Build
parser.parse(new InputSource(new FileReader(fileName));
// Get indented XML as String from handler
String identedXML = handler.getResult();

答案 4 :(得分:2)

来自Java 8 Core API的非常好的示例是Calendar,例如,您可以使用:

Calendar cal = new Calendar.Builder().setCalendarType("iso8601")
                        .setWeekDate(2013, 1, MONDAY).build();

来自Java 7的另一个好例子是Locale,使用:

Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();

构建器模式在不可变对象的上下文中最有用。有趣的是,Java中有许多可变构建器,StringBuilder是最常见的构建器。来自Java 8的可变构建器:

  • Stream.Builder
  • IntStream.Builder
  • LongStream.Builder
  • DoubleStream.Builder

答案 5 :(得分:1)

ProcessBuilder是构建器模式的一个实例,但并不完全使用java命名约定。

 ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
 Map env = pb.environment();
 env.put("VAR1", "myValue");
 env.remove("OTHERVAR");
 env.put("VAR2", env.get("VAR1") + "suffix");
 pb.directory(new File("myDir"));
 Process p = pb.start();

在SQL包中,PreparedStatement可以被视为构建器模式的一个实例:

 PreparedStatement stmt = conn.prepareStatement(getSql());
 stmt.setString(1, ...);
 stmt.setString(2, ...);
 ResultSet rs = stmt.executeQuery();
 ...
 stmt.setString(2, ...);
 rs = stmt.executeQuery();
 ...

答案 6 :(得分:0)

它仅在标准库中定义(未实现),但是,JDBC DataSource对象提醒我构建器模式。您创建一个DataSource对象,然后设置许多属性,然后建立连接。

这是一个代码示例......

DataSource ds = (DataSource)ctx.lookup("jdbc/AcmeDB");
ds.setServerName("my_database_server");
ds.setDescription("the data source for inventory and personnel");
Connection con = ds.getConnection("genius", "abracadabra");