【问题标题】:F# - Factory Method Design PatternF# - 工厂方法设计模式
【发布时间】:2011-04-15 01:02:16
【问题描述】:

以下是我尝试使用 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

这是工厂方法设计模式的适当实现吗?该模式是否用于现实世界的 F# 应用程序?

【问题讨论】:

  • +1 为你肩上的猴子。
  • @Juliet 谢谢。一定要爱猴子:)。
  • 滑板厂+1!
  • @krookedking +1 为被骗的国王

标签: design-patterns f#


【解决方案1】:

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

  • 当您以函数式方式使用 F# 时,您将在大部分时间使用具体表示。例如,这使您能够在滑板类型上进行模式匹配。
  • 当然,F# 允许您将函数式风格与面向对象风格混合。出于某些目的,OO 风格在 F# 中运行良好。在这种情况下,您的方法看起来很合理。

您的工厂方法可以将具体类型(例如可区分联合)作为参数,而不是字符串。那么工厂的任务就是从具体表示中构建抽象表示:

// Abstract representation of the data
type ISkateBoard = 
  abstract Model : unit -> string

// Concrete representation of the data
type SkateBoard = 
  | Roskopp 
  | Peters

现在,工厂只是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..." }

我认为这种方法的好处是您可以对类型的具体表示做一些工作(例如,您需要模式匹配的一些计算),但是您可以使用factory 来转换具体类型变成抽象类型。

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

【讨论】:

  • 感谢您的澄清,另外我喜欢您提出的解决方案。
【解决方案2】:

正如 Tomas 所说,使用具体类型可以让您在开始使用工厂创建对象之前清理输入并失败。

type SkateBoard = 
    | Roskopp 
    | Peters
with 
    static member FromString = function
        | "Roskopp" -> Roskopp
        | "Peters" -> Peters            
        |  _ -> failwith "no such skateboard model.."

你会发现很多来自 OO 的设计模式在函数式编程中消失了。

使用SkateBoardFactory,您可以创建一个额外的函数来执行您的函数。

let SkateBoardFactory assemble model = assemble model
let SantaCruzFactory = SkateBoardFactory assemble

由于一流的功能,您可以简单地分配assemble

let SantaCruzFactory = assemble

【讨论】: