Java API 中的构建器模式示例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2169190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:49:20  来源:igfitidea点击:

Example of Builder Pattern in Java API?

javadesign-patternsbuilder

提问by Fostah

Joshua Bloch's Effective Javadescribes a Builder Pattern that can be used to build objects with several optionally customizable parameters. The naming convention he suggests for the Builder functions, which "simulates named optional parameters as found in Ada and Python," doesn't seem to fall in line with Java's standard naming convention. Java functions tend to rely on a having a verb to start the function and then a noun-based phrase to describe what it does. The Builder class only has the name of the variable that's to be defined by that function.

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

Are there any APIs within the Java standard libraries that makes use of the Builder Pattern? I want to compare the suggestions in the book to an actual implementation within the core set of Java libraries before pursuing its use.

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

回答by Jon Skeet

I'm not sure about within the core JDK, but good examples can be found in Guava. MapMakeris probably the best example I can think of off the top of my head. For example, from the docs:

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

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

Yes, this sort of thing can go against the grain of "standard" Java naming, but it can also be very readable.

是的,这种事情可能会违背“标准”Java 命名的原则,但它也非常具有可读性。

For situations where you're not returning "this" but a new object (typically with immutable types) I like a "with" prefix - Joda Time uses that pattern extensively. That's not the builder pattern, but an alternative and related construction form.

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

回答by Tanya Kogan

Locale class has an example of the Builder pattern. https://docs.oracle.com/javase/7/docs/api/java/util/Locale.Builder.html

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

Usage:

用法:

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

回答by John Brown

The only builder most accurate to the Effective java book is StringBuilder. The only difference I see from the example is that this builder is not an inner class of String.

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

All the methods return the builder object to chain. and the toString() method is the build() method.

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

回答by Anil Bhaskar

Pretty good example from Java 8 Core API is Calendar, for example you can use:

Java 8 Core API 的一个很好的例子是Calendar,例如你可以使用:

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

Another good example from Java 7is Locale, use:

另一个很好的例子Java 7Locale,使用:

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

The builder pattern is most useful in the context of immutable objects. Interestingly there are many mutable builders in Java, StringBuilderbeing the most common one. Mutable builders from Java 8:

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

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

回答by jk_

SAXParserseems to be good example:

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

  • SAXParser- Director
  • ContentHandler- Builder
  • SAXParser- 导演
  • ContentHandler- 建造者

The typical usage of SAXParseris identical with Builder:

的典型用法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();

回答by Sarah Happy

ProcessBuilder is very much an instance of the builder pattern, but not quite using the java naming conventions.

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();

In the SQL package, PreparedStatement could be considered an instance of the builder pattern:

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

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

回答by Pace

It's only defined (not implemented) in the standard library, however, the JDBC DataSource objects remind me of the builder pattern. You create a DataSource object and then you set a number of properties and then you make a connection.

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

Here's a code example...

这是一个代码示例...

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");