Статьи

Шаблон Builder с использованием Java 8

Я работаю в среде, где большая часть наших повседневных задач сценариев происходит через вызов удаленных служб, а не работу с базой данных.

Для многих задач написания сценариев я часто использовал Groovy, и одна из самых полезных функций Groovy специально для этой задачи заключалась в том, что она была построена на быстрых сборщиках .

Теперь сборщики Groovy используют несколько возможностей языка Groovy, которые никогда не превратятся в Java.

В частности, сборщики Groovy используют возможности Meta-программирования Groovy, которые скоро появятся в Java.

Однако ключевой особенностью Groovy-строителей является их иерархический подход к построению конструкций.

Это позволяет разработчикам аккуратно и безопасно создавать вложенные древовидные конструкции, которые можно использовать для моделирования всего, от макетов форм UX до XML.

При таком подходе мы, по крайней мере, можем довольно кратко смоделировать, используя лямбда-выражения Java 8

Для моего примера я решил взять достаточно простой файл Maven pom и посмотреть, смогу ли я создать конструктор для этого.

Весь код для сборщика доступен на Github здесь .

Файл pom.xml выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?> 
   <modelVersion>4.0.0</modelVersion
   <groupId>com.github</groupId
   <artifactId>lambda-builder</artifactId
   <version>1.0-SNAPSHOT</version
   <dependencies
     <dependency
       <groupId>junit</groupId
       <artifactId>junit</artifactId
       <version>4.11</version
     </dependency
     <dependency
       <groupId>commons-beanutils</groupId
       <artifactId>commons-beanutils</artifactId
       <version>1.7.0</version
     </dependency
   </dependencies
   <build
     <plugins
       <plugin
         <groupId>org.apache.maven.plugins</groupId
         <artifactId>maven-compiler-plugin</artifactId
         <configuration
           <source>1.8</source
           <target>1.8</target
           <fork>true</fork
           <compilerArgument>-proc:none</compilerArgument
         </configuration
       </plugin
     </plugins
   </build
 </project>

Вот пример кода для строителя, чтобы построить эту модель:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
MarkupBuilder pom = new XmlMarkupBuilder(true, "pom"
         .at("xmlns", "http://maven.apache.org/POM/4.0.0"
         .at("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"
         .at("xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"); 
     pom.el("modelVersion", "4.0.0"); 
     pom.el("groupId", "com.github"); 
     pom.el("artifactId", "lambda-builder"); 
     pom.el("version", "1.0-SNAPSHOT"); 
     pom.el("dependencies", () -> { 
       pom.el("dependency", () -> { 
         pom.el("groupId", "junit"); 
         pom.el("artifactId", "junit"); 
         pom.elx("version", version::get); 
       }); 
       pom.el("dependency", () -> { 
         pom.el("groupId", "commons-beanutils"); 
         pom.el("artifactId", "commons-beanutils"); 
         pom.elx("version", version::get); 
       }); 
     }); 
     pom.el("build", () -> { 
       pom.el("plugins", () -> { 
         pom.el("plugin", () -> { 
           pom.el("groupId", "org.apache.maven.plugins"); 
           pom.el("artifactId", "maven-compiler-plugin"); 
           pom.el("configuration", () -> { 
             pom.el("source", 1.8); 
             pom.el("target", 1.8); 
             pom.el("fork", true); 
             pom.el("compilerArgument", "-proc:none"); 
           }); 
         }); 
       }); 
     });

Несколько замечаний по этому поводу в целом:

  • Я создал специальную форму некоторых методов, которая принимает java.util.function.Supplier в качестве параметра и позволяет вам отложить оценку значения до тех пор, пока вы не пройдете по построителю.
  • Я избегал метода цепочки (хотя я учел это в конструкторе). Пробуя оба метода, я лично чувствовал, что это намного чище.
  • У Java нет всего синтаксического сахара, который есть у Groovy, поэтому я использовал java.lang.Runnable для функционального интерфейса, который уменьшил синтаксис, создавая замыкание, с недостатком, что у вас должен быть дескриптор исходного объекта компоновщика.

Нигде так хорошо, как Groovy строители, но, тем не менее, большой шаг вперед. Не могу дождаться Java 8.

Ссылка: Шаблон Builder с использованием Java 8 от нашего партнера JCG Джулиана Эксенбергера из блога Dot Neverland .