Пример шаблона Builder в Java API?
Joshua Bloch Эффективная Java описывает шаблон Builder, который можно использовать для создания объектов с несколькими необязательно настраиваемыми параметрами. Соглашение об именовании, которое он предлагает для функций Builder, которое "имитирует именованные дополнительные параметры, найденные в Ada и Python", похоже, не соответствует стандарту стандартного именования Java. Функции Java, как правило, полагаются на наличие глагола для запуска функции, а затем именную фразу для описания того, что она делает. Класс Builder имеет только имя переменной, которая должна быть определена этой функцией.
Существуют ли какие-либо API в стандартных библиотеках Java, которые используют шаблон Builder? Я хочу сравнить предложения в книге с фактической реализацией в основном наборе библиотек Java, прежде чем использовать его.
Ответы
Ответ 1
Я не уверен в основном 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);
}
});
Да, такого рода вещи могут пойти против зерна "стандартного" именования Java, но также могут быть очень читабельными.
В ситуациях, когда вы не возвращаете "this", а новый объект (обычно с неизменяемыми типами), мне нравится префикс "с". Время Joda Time широко использует этот шаблон. Это не шаблон строителя, а альтернативная и связанная с ним конструкция.
Ответ 2
Единственным строителем, наиболее точным для эффективной Java-книги, является StringBuilder.
Единственное отличие, которое я вижу в этом примере, состоит в том, что этот строитель не является внутренним классом String.
Все методы возвращают объект-строитель в цепочку. а метод toString() - метод build().
Ответ 3
В классе 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();
Ответ 4
Он только определен (не реализован) в стандартной библиотеке, однако объекты DataSource JDBC напоминают мне шаблон построителя. Вы создаете объект 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");
Ответ 5
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
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();
Ответ 7
Довольно хороший пример из 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
является наиболее распространенным. Mutable builders из Java 8:
-
Stream.Builder
-
IntStream.Builder
-
LongStream.Builder
-
DoubleStream.Builder