Пример шаблона Builder в Java API?
Джошуа Блохаэффективная Java описывает шаблон компоновщика, который может быть использован для построения объектов с несколькими опционально настраиваемыми параметрами. Соглашение об именовании, которое он предлагает для функций Builder, которое "имитирует именованные необязательные параметры, найденные в Ada и Python", похоже, не соответствует стандартному соглашению об именовании Java. Функции Java, как правило, полагаются на наличие глагола, чтобы запустить функцию, а затем фразу на основе существительного, чтобы описать, что она делает. То Класс Builder имеет только имя переменной, которая должна быть определена этой функцией.
Существуют ли какие-либо API в стандартных библиотеках Java, которые используют шаблон Builder? Я хочу сравнить предложения в книге с фактической реализацией в основном наборе библиотек Java, прежде чем продолжить его использование.
7 ответов:
Я не уверен насчет ядра 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-именами, но они также могут быть очень удобочитаемыми.
Для ситуаций, когда вы возвращаете не "это", а новый объект (обычно с неизменяемыми типами), мне нравится префикс "с" - Joda Time использует это картина обширна. Это не модель строителя, а альтернативная и связанная с ней форма строительства.
Единственным построителем, Наиболее точным для эффективной книги java, является StringBuilder. Единственное отличие, которое я вижу из примера, заключается в том, что этот конструктор не является внутренним классом строки.
Все методы возвращают объект builder в цепочку. а метод toString () - это метод build ().
Locale класс и пример шаблона. https://docs.oracle.com/javase/7/docs/api/java/util/Locale.Builder.html
Использование:
Locale locale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
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();
Довольно хорошим примером из 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
Он только определен (не реализован) в стандартной библиотеке, однако объекты источника данных JDBC напоминают мне шаблон builder. Вы создаете объект источника данных, а затем устанавливаете ряд свойств и устанавливаете соединение.
Вот пример кода...
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");
ProcessBuilder в значительной степени является экземпляром шаблона builder, но не совсем использует соглашения об именовании 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 можно рассматривать как экземпляр шаблона builder:
PreparedStatement stmt = conn.prepareStatement(getSql()); stmt.setString(1, ...); stmt.setString(2, ...); ResultSet rs = stmt.executeQuery(); ... stmt.setString(2, ...); rs = stmt.executeQuery(); ...