Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 什么';构建模式的clojure方法是什么?_Design Patterns_Clojure_Builder - Fatal编程技术网

Design patterns 什么';构建模式的clojure方法是什么?

Design patterns 什么';构建模式的clojure方法是什么?,design-patterns,clojure,builder,Design Patterns,Clojure,Builder,我们通常在java中使用生成器模式,如下所示: UserBuilder userBuilder = new UserBuilder(); User John = userBuiler.setName("John") .setPassword("1234") .isVip(true) .visableByPublic(false)

我们通常在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}))
因此,我的问题是,有没有一种优雅的方法来实现这一点?

一种简单的方法是使用宏:

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

(def al (doto (java.util.ArrayList.) (.add 11) (.add 3)(.add 7)))
斯图尔特对如何将doto与Swing结合使用有所了解。 这里有一个小组:

(doto (JPanel.)
            (.setOpaque true)
            (.add label)
            (.add button))
这里有一个框架:

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

如果您想构造一些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对象(使用其setter),可以使用Nicolas建议的方法。

我通常会通过映射传入属性-这样做没有真正的问题,因为属性映射实际上只是make user函数的一个参数。您还可以在默认属性中进行类似用户的合并

如果确实希望使用生成器模式构建这样的映射,可以使用线程宏来实现,如下所示:

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

(def john(使用户{:name“john”:pass“1234”:vip true:visible false}))

分成多行:

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

为了完整起见,没有人提到自动为您提供“构建器函数”

(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}

为了完整性,回答您的默认值,使用
解构支持默认值:
(defn使用户[&{:keys[name pass vip visible]:或{vip true}]
是的,你完全正确。我还要补充一点,如果变量默认值没有在
:或
映射中设置,并且在实际调用中没有指定,它将变为
nil
。你如何想象画眉鸟(
->
)将代替
doto
,因为这些方法调用的返回值不是
this
?是的,你是对的。不知何故,我在写作时不记得这一点,我也不记得(显然是错的)我想我在某些地方看到了这些宏的可互换性。删除了这个通知。在我看来,生成器模式实际上只是缺少命名参数的一个解决办法。初始化一组仅作为位置参数区分的字段非常麻烦,以后很难阅读,因此生成器模式。Map destructuring在单个函数调用中实现了相同的目标,正如Ankur建议的那样,将地图拆分为多行以保持可读性。