F# - 工厂方法设计模式

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# 应用程序中使用?

Tom*_*cek 5

我不确定工厂方法设计模式在函数式编程中的有用程度。该模式的目标是隐藏对象的创建,以便您可以仅使用对象的抽象表示。

  • 当您以函数方式使用 F# 时,大部分时间您将使用具体表示。例如,这使您能够在滑板类型上进行模式匹配。
  • 当然,F# 允许您将函数式风格与面向对象风格相结合。出于某些目的,OO 风格在 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将具体类型转换为抽象类型。

这与函数式编程中的常用方法非常匹配 - 您经常使用一个数据的不同表示并在它们之间进行转换(取决于哪种表示更适合特定问题)。


gra*_*bot 5

正如 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)