Dav*_*son 5 f# design-patterns
下面是我尝试使用 F# 实现工厂方法设计模式,同时尝试使其更具功能性(即不是直接的 OO 实现)。以下是我想出的:
type ISkateBoard = abstract Model : unit -> string
type SkateBoard =
| Roskopp
| Peters
interface ISkateBoard
with member this.Model() =
match this with
| Roskopp-> "Rob Roskopp..."
| Peters -> "Duane Peters..."
let assemble model : ISkateBoard =
match model with
| "Roskopp" -> Roskopp :> ISkateBoard
| "Peters" -> Peters :> ISkateBoard
| _ -> failwith "no such skateboard model.."
let SkateBoardFactory assemble model = assemble model
let SantaCruzFactory = SkateBoardFactory assemble
Run Code Online (Sandbox Code Playgroud)
这是工厂方法设计模式的适当实现吗?该模式是否在现实世界的 F# 应用程序中使用?
我不确定工厂方法设计模式在函数式编程中的有用程度。该模式的目标是隐藏对象的创建,以便您可以仅使用对象的抽象表示。
您的工厂方法可以采用具体类型(例如可区分联合)作为参数,而不是字符串。那么工厂的任务就是从具体表示中构建抽象表示:
// Abstract representation of the data
type ISkateBoard =
abstract Model : unit -> string
// Concrete representation of the data
type SkateBoard =
| Roskopp
| Peters
Run Code Online (Sandbox Code Playgroud)
现在,工厂只是一个 type 的函数SkateBoard -> ISkateBoard。例如(使用 F# 对象表达式):
// Transform concrete representation to abstract representation
let factory concrete =
match concrete with
| Roskopp -> { new ISkateBoard with
member x.Model() = "Rob Roskopp..." }
| Peters -> { new ISkateBoard with
member x.Model() = "Duane Peters..." }
Run Code Online (Sandbox Code Playgroud)
我认为这种方法的好处是你可以在类型的具体表示上做一些工作(例如一些需要模式匹配的计算),但是你可以使用factory将具体类型转换为抽象类型。
这与函数式编程中的常用方法非常匹配 - 您经常使用一个数据的不同表示并在它们之间进行转换(取决于哪种表示更适合特定问题)。
正如 Tomas 所说,使用具体类型可以让您在开始使用工厂创建对象之前清理输入并失败。
type SkateBoard =
| Roskopp
| Peters
with
static member FromString = function
| "Roskopp" -> Roskopp
| "Peters" -> Peters
| _ -> failwith "no such skateboard model.."
Run Code Online (Sandbox Code Playgroud)
你会发现很多 OO 的设计模式在函数式编程中消失了。
随着SkateBoardFactory您创建一个额外的功能来执行您的功能。
let SkateBoardFactory assemble model = assemble model
let SantaCruzFactory = SkateBoardFactory assemble
Run Code Online (Sandbox Code Playgroud)
assemble由于一流的功能,您可以简单地分配。
let SantaCruzFactory = assemble
Run Code Online (Sandbox Code Playgroud)