JavaAPI中的生成器模式示例?

JavaAPI中的生成器模式示例?,java,design-patterns,builder,Java,Design Patterns,Builder,Joshua Bloch的高效Java描述了一种构建器模式,可用于构建具有多个可选自定义参数的对象。他为构建器函数建议的命名约定“模拟Ada和Python中的命名可选参数”,似乎不符合Java的标准命名约定。Java函数倾向于使用动词启动函数,然后使用基于名词的短语来描述函数的功能。生成器类只有该函数定义的变量的名称 Java标准库中是否有使用Builder模式的API?在继续使用Java库之前,我想将书中的建议与核心Java库集中的实际实现进行比较 它只在标准库中定义(未实现),但是,JDBC

Joshua Bloch的高效Java描述了一种构建器模式,可用于构建具有多个可选自定义参数的对象。他为构建器函数建议的命名约定“模拟Ada和Python中的命名可选参数”,似乎不符合Java的标准命名约定。Java函数倾向于使用动词启动函数,然后使用基于名词的短语来描述函数的功能。生成器类只有该函数定义的变量的名称

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

它只在标准库中定义(未实现),但是,JDBC数据源对象让我想起了构建器模式。创建一个数据源对象,然后设置若干属性,然后建立连接

下面是一个代码示例

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

我不确定核心JDK中是否有,但是可以在中找到好的示例。这可能是我脑海中能想到的最好的例子。例如,从文档中:

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);
          }
        });
ConcurrentMap graphs=newmapmaker()
.1级(32)
.软键()
.weakValues()
.有效期(30,时间单位:分钟)
.makeComputingMap(
新函数(){
公共图形应用(密钥){
返回createExpensiveGraph(键);
}
});
是的,这类东西可能与“标准”Java命名格格不入,但也可能非常可读


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

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(); ProcessBuilder pb=新的ProcessBuilder(“myCommand”、“myArg1”、“myArg2”); Map env=pb.environment(); 环境看跌期权(“VAR1”、“myValue”); 环境移除(“其他变量”); 环境put(“VAR2”,环境get(“VAR1”)+“后缀”); 目录(新文件(“myDir”); 进程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(); ... PreparedStatement stmt=conn.prepareStatement(getSql()); stmt.setString(1,…); stmt.setString(2,…); ResultSet rs=stmt.executeQuery(); ... stmt.setString(2,…); rs=stmt.executeQuery(); ...
对于有效的java书籍来说,唯一最准确的构建器是StringBuilder。 我从示例中看到的唯一区别是,此生成器不是字符串的内部类


所有方法都将生成器对象返回到链。toString()方法就是build()方法。

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

  • SAXParser
    -控制器
  • ContentHandler
    -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();

Locale类有一个生成器模式的示例。

用法:

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

Java 8 Core API中相当好的示例是,例如,您可以使用:

Calendar cal=new Calendar.Builder().setCalendarType(“iso8601”)
.setWeekDate(2013年1月1日星期一).build();
Java 7
的另一个好例子是,使用:

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

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

如果你不能链接方法,它就不是一个完全值得使用的构建器模式。你可以在这个问题中找到例子:
StringBuilder
不是构建器模式的一个实现,只是因为它的名字是builder,它不返回一个新的
对象
,而是相反。和平。@AnilBhaskar你能解释一下为什么
StringBuilder
不遵循生成器模式吗?在这个实现中,至少创建了一个新的(防御的)
字符串。“with”前缀的这种用法是一种更常用的惯例吗?对于返回this
的生成器类,我总是使用带前缀的。我认为这在语义上也是由“with”表示的:带有属性的实例=修改它。@kap:是的,“with”前缀是一个相当常见的约定,我个人认为“with”修改其他东西没有意义。请注意,这在C#9中非常常见,它正在成为语言的一部分(就记录类型生成的内容而言):@kap:java.time也非常广泛地使用它,例如
LocalDate.withMonth
等。
Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();