在swannodettes clojurescript教程(https://github.com/swannodette/lt-cljs-tutorial/blob/master/lt-cljs-tutorial.cljs)中,声称:
定义工厂功能被认为是惯用的(并推荐) 返回创建的defrecord / deftype实例。这是惯用的 工厂名称的破折号。
以示例:
(defn person [first last]
(->Person first last))
为什么?
我唯一能想到的是,如果你使用一组参数并且它们与实现不匹配,那么作为转换:
(defn person [full-name]
(->Person (first (split full-name)) ... ))
或作为防止在用作库时更改实现。
是吗?缺点是额外的,不必要的功能,需要与实现并行更新,并且可能稍微不清楚名称。
我不喜欢样板代码,所以在没有解释的情况下给出这样的建议时我总是很沮丧。
答案 0 :(得分:1)
Java允许具有不同签名IE
的多个构造函数public class Foo implements Bar {
private final Boolean initialState;
public Foo () { this.initialState = false; }
public Foo (Boolean initialState) { this.initialState = initialState; }
public void sayState () {System.out.println(this.initialState)}
}
无法以这种方式定制Clojure构造函数。您基本上可以根据提供给defrecord
的字段向量为您创建一个构造函数。
(defrecord Foo [initial-state] Bar (sayState [this] (println initial-state)))
因此,如果你想根据与defrecord
的字段向量不匹配的签名构造一个对象,你需要一个包装器fn来设置初始状态的默认值。
如果defrecord
的字段向量发生变化,则工厂方法将来证明您不必更改代码中(->Foo state)
的所有出现次数。
答案 1 :(得分:1)
或作为防止在用作库时更改实现。
是吗?
我认为就是这样。
如果您的记录仅供内部使用,那么只使用其中一个提供的构造函数就可以做到最直接。也许您已经使用地图进行了原型设计,并且由于某种原因意识到您需要记录。所以(可能)没有回头,->Record
& map->Record
没问题。
但是当您为其他人提供API时,它应该尽可能稳定。你不想让消费者感到惊讶并让他们进行大规模的重构。至少,通过提供自定义构造函数,您可以生成明确的弃用警告。
我通常会考虑->Record
& map->Record
构造器实现细节并隐藏它们。
TL; DR:当您编写一个可能被其他一千个人使用的库时,您自己编写代码,为自己和另一个故事编写代码,这是一个不同的故事。