构建器模式和DSL等效 - 还是更具表现力?

时间:2014-08-17 05:59:35

标签: java scala clojure dsl builder

假设

  • 我将此限制为internal DSLs - 但如果你能给我一个很好的理由我应该考虑external DSLs - 我会听取这个。
  • 如果你想在Clojure或Scala中回答这个问题并解释为什么我错了 - 我也很酷。

前几天我听到一位朋友说:

  

你知道,DSLbuilder pattern - 它们基本上是一回事。

对我来说这听起来很奇怪,因为我一直认为DSL总是比Builder模式更具表现力。

我的问题是:构建器模式和DSL等效 - 还是更具表现力?

所以我看了一下 - 这是一个User Builder Pattern in Java

public class User {
    private final String firstName; // required
    private final String lastName; // required
    private final int age; // optional
    private final String phone; // optional
    private final String address; // optional

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public static class UserBuilder {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            return new User(this);
        }

    }
}

以下是使用的上述构建器模式:

public User getUser() {
    return new
        User.UserBuilder("John", "Doe")
        .age(30)
        .phone("1234567")
        .address("Fake address 1234")
        .build();
}

以下是usage of an Internal DSL in Java

 Person person = constructor().withParameterTypes(String.class)
                              .in(Person.class)
                              .newInstance("Yoda");

 method("setName").withParameterTypes(String.class)
                  .in(person)
                  .invoke("Luke");

 field("name").ofType(String.class)
              .in(person)
              .set("Anakin"); 

3 个答案:

答案 0 :(得分:4)

我认为你甚至不能比较这两个不同的概念。

DSL是特定域的语言,但它具有原语和组合规则,允许您谈论特定域。

构建器模式是一种模式,即解决方案模板,您应用于问题以提出解决方案,然后您使用该解决方案。在您的代码示例中,UserBuilder类不应用构建器模式,它本身不是构建器模式。

您似乎正试图在语法上比较它们,因为您的示例代码正在尝试显示。在两个示例代码中,您在语法上显示DSL和构建器模式类都具有相同的功能,即方法调用链,这导致您可以比较它们。我不认为比较是公平的,因为只能让你用同一种语言比较它们,即无法在不同的编程语言中进行语法比较。

您可以使用构建器模式实现DSL,也可以使用其他模式实现DSL。模式是一组问题的解决方案模板,构建器模式是实现DSL问题的一个这样的模板,但它不是唯一的模板。

答案 1 :(得分:0)

当然,DSL包含许多不是构建器模式的东西。所以不,他们不是一回事。

如果你认为每个构建器模式都是DSL(对于构造特定类的对象的域),那么你显然会得到一般的DSL比构建器模式更具表现力。但 a DSL并不比构建器模式更具表现力;任何单个DSL都无法完成构建器模式可以执行的所有操作。

答案 2 :(得分:0)

如果你的朋友说了

  

你知道,用于构建Plain Old Java Objects ,构建器模式是一种DSL。

......然后我同意了。

但是,在Clojure中,您不需要构建器类或DSL来简洁地构造对象。

  • POJO转化为记录,模仿(哈希)地图。有点笨重 从地图创建记录的语法。

鉴于

(defrecord User [first-name last-name age phone address])

......然后

(map->User {:first-name "John"
            :last-name "Doe"
            :address "Fake address 1234"})

...生产

{:first-name "John",
 :last-name "Doe",
 :age nil,
 :phone nil,
 :address "Fake address 1234"}

...这是一张User记录,虽然它打印得像地图一样。

因此,为此目的,Clojure将 DS DSL 中取出,您只需要使用语言结构。