繁体   English   中英

F# 命令模式

[英]F# Command Pattern

我正在尝试实现命令模式来控制机器人。 我正在使用它来探索如何在 F# 中实现命令模式。 下面是我的实现:

type Walle(position, rotate) =     
    let (x:float,y:float) = position
    let rotation = rotate
    member this.Move(distance) =
        let x2 = distance * sin (System.Math.PI/180.0 * rotation)
        let y2 = distance * cos (System.Math.PI/180.0 * rotation)
        let newPosition = (x+x2, y+y2)
        Walle(newPosition, rotation)
    member this.Rotate(angle) = 
        let newRotation = 
            let nr = rotation + angle
            match nr with
            | n when n < 360.0 -> nr
            | _ -> nr - 360.0
        Walle(position, newRotation)

let Move distance = fun (w:Walle) -> w.Move(distance)
let Rotate degrees = fun (w:Walle) -> w.Rotate(degrees)

let remoteControl (commands:List<Walle->Walle>) robot = 
    commands |> List.fold(fun w c -> c w)

let testRobot() =
    let commands = [Move(10.0);Rotate(90.0);Move(16.0);Rotate(90.0);Move(5.0)]
    let init = Walle((0.0,0.0),0.0)
    remoteControl commands init

为了提出一个功能解决方案,我选择让机器人的动作在每次调用后在其新的 position 处返回一个机器人的新实例(避免突变)。 我还关闭了执行操作所需的 state 的命令功能。

我很好奇人们在实现该模式时是否认为这些是好的设计决策? 或者,如果人们可以就实施该模式提供任何其他建议?

为了避免采用 OO 方式将数据与“类型”中的操作组合并将这种组合表示为“对象”,我的 POV 中更实用的方法是在模块中分别定义数据和操作,如下所示:

module Walle = 
 type Walle = {Position : float * float; Rotation : float}

 let Move distance (w:Walle) = 
    let x2 = distance * sin (System.Math.PI/180.0 * w.Rotation)        
    let y2 = distance * cos (System.Math.PI/180.0 * w.Rotation)
    {w with Position = (w.Position |> fst) + x2, (w.Position |> snd) + y2 }

 let Rotate angle (w:Walle) = 
    let newRotation = 
        let nr = w.Rotation + angle
        match nr with
        | n when n < 360.0 -> nr
        | _ -> nr - 360.0
    {w with Rotation = newRotation}

现在您可以创建一个新的 Walle 并使用 |> function 将其传递给一系列转换 Walle“数据”的函数。 这完全是关于数据和该数据的转换,没有对象:)。 它可能不像命令模式,因为它更适合 OO 风格。 您真的不需要 FP 中的模式,还是我们?

对于机器人示例,我宁愿只使用命令式样式,即更改机器人 object 的状态。 因为机器人 object 通常有状态的概念和改变状态的动作。 从OO设计的角度来看,有些对象最好是不可变的,例如.NET中的String、DateTime,但很多都不是。

不可变对象当然有优势。 在您问题的持久版本中,您可以保存机器人的所有过去状态,并且可以轻松地UnDo机器人上的命令。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM