變化狀態位於構建器模式的中心。有沒有一種慣用的方式來實現F#中這樣一個類的內部實現,它將減少/消除可變狀態,同時保留通常的接口(該類將主要用於其他.NET語言)?在F#中實現構建器模式(a System.Text.StringBuilder)
這裏有一個天真的實現:
type QueryBuilder<'T>() = //'
let where = ref None
let orderBy = ref None
let groupBy = ref None
member x.Where(cond) =
match !where with
| None -> where := Some(cond)
| _ -> invalidOp "Multiple WHERE clauses are not permitted"
// members OrderBy and GroupBy implemented similarly
一個想法是創建一個記錄類型來存儲的內部結構,並使用複製和更新表達式。
type private QueryBuilderSpec<'T> = //'
{ Where : ('T -> bool) option; //'
OrderBy : (('T -> obj) * bool) list; //'
GroupBy : ('T -> obj) list } //'
type QueryBuilder<'T>() = //'
let spec = ref None
member x.Where(cond) =
match !spec with
| None ->
spec := Some({ Where = Some(cond); OrderBy = []; GroupBy = [] })
| Some({ Where = None; OrderBy = _; GroupBy = _} as s) ->
spec := Some({ s with Where = Some(cond) })
| _ -> invalidOp "Multiple WHERE clauses are not permitted"
// members OrderBy and GroupBy implemented similarly
這一切似乎有點笨重,也許應該努力實現F#勢在必行模式時,可以預期的。有沒有更好的方法來做到這一點,再次,爲了命令式語言而保留常用的構建器界面?
我並沒有真正看到你的建設者之間有太大的區別。任何一個都可以從外部變化,而不管第一種還是第二種方式都沒有實現。 –
沒錯。我沒有看到消除可變狀態的任何方法。不同之處在於第一個實現可以包含任意數量的可變變量。第二個實現有一個。是的,也許這是一個微不足道的區別。我討厭這兩個,但這是我需要建立的。我更喜歡F#,但也許我需要回到C#來做到這一點。只是以爲在放棄F#之前我會得到更多的意見。 – Daniel