构建模式的 clojure 方法是什么?



我们通常在java中使用构建器模式,如下所示:

UserBuilder userBuilder = new UserBuilder();
User John = userBuiler.setName("John")
                      .setPassword("1234")
                      .isVip(true)
                      .visableByPublic(false)
                      .build();
某些属性

具有默认值,而某些属性则没有。

在映射中传递属性可能是一种解决方案,但它会使参数变得更长:

(def john (make-user {:name "John" :pass "1234" :vip true :visible false}))

所以,我的问题是,有没有一种优雅的方式来实现这一目标?

如果你想构造一些clojure结构,你可以在函数参数中使用解构模式。然后,您将实现您已经写过的类似内容。

(defn make-user [& {:keys [name pass vip visible]}]
  ; Here name, pass, vip and visible are regular variables
  ; Do what you want with them
)
(def user (make-user :name "Name" :pass "Pass" :vip false :visible true))

我怀疑你能用比这更少的代码做一些事情。

如果你想构造Java对象(使用它的setters),你可以使用Nicolas建议的方法。

我通常会通过映射传递属性 - 这样做没有真正的问题,因为属性映射实际上只是make-user函数的一个参数。你也可以在make-user中做一些好事,比如在默认属性中合并。

如果你真的想用构建器模式构造这样的映射,你可以使用线程宏来完成,如下所示:

(def john 
  (-> {}
    (assoc :name "John")
    (assoc :pass "1234")
    (assoc :vip true)
    (assoc :visible false)
    make-user))
重写

(def john (make-user {:name "John" :pass "1234" :vip true :visible false}))

分为多行:

(def john (make-user {:name "John" 
                      :pass "1234" 
                      :vip true 
                      :visible false}))

一个简单的方法是使用 doto 宏:

下面是使用一些值填充数组列表的示例:

(def al (doto (java.util.ArrayList.) (.add 11) (.add 3)(.add 7)))

Stuart有一些关于如何将doto与Swing一起使用的完美例子。这里有一个面板:

(doto (JPanel.)
            (.setOpaque true)
            (.add label)
            (.add button))

这里有一个框架:

(doto (JFrame. "Counter App")
  (.setContentPane panel)
  (.setSize 300 100)
  (.setVisible true))

为了完整起见,没有人提到 defrecord,它会自动为您提供"构建器函数"

(defrecord User [name pass vip visible])
(User. "John" "1234" true false)
;;=>#user.User{:name "John", :pass "1234", :vip true, :visible false}
(->User "John" "1234" true false)
;;=>#user.User{:name "John", :pass "1234", :vip true, :visible false}
(map->User {:name "John" :pass "1234" :vip true :visible false})
;;=>#user.User{:name "John", :pass "1234", :vip true, :visible false}

最新更新