Loading

学习笔记-涛讲F#(中级)


这一系列的视频主要讲了F#设计模式的实现,没有太多其它内容,笔记内容主要是转载Snippets tagged design patterns的代码用于备份。设计模式相关的概念可参考设计模式:23种设计模式全面解析,本文不做太多介绍。

适配器模式

从不兼容的类型调用方法——原文链接

type Cat() = 
    member this.Walk() = printfn "cat walk"
type Dog() = 
    member this.Walk() = printfn "dog walk"

let adapter() = 
    let cat = Cat()
    let dog = Dog()
    let inline walk (x : ^T) = (^T : (member Walk : unit->unit) (x))
    walk(cat)
    walk(dog)

适配器模式的主要功能是由 inline 这行函数实现的,调用时直接使用 adapter() 即可。inline不可省略——因为内联函数可以具有静态解析的类型参数,而非内联函数不能

责任链模式

以下示例要确保此人的年龄在 18 到 65 岁之间,体重不超过 200 并且足够高(>120)——原文链接

type Record = {
    Name : string;
    Age : int;
    Weight: float;
    Height: float;
}

let ChainOfResponsibility() = 
    let validAge (record:Record) = 
        record.Age < 65 && record.Age > 18
    let validWeight (record:Record) = 
        record.Weight < 200.
    let validHeight (record:Record) = 
        record.Height > 120.

    let check (f:Record->bool) (record:Record, result:bool) = 
        if result=false then (record, false)
        else (record, f(record))

    let chainOfResponsibility = check(validAge) >> check(validWeight) >> check(validHeight)

    let john = { Name = "John"; Age = 80; Weight = 180.; Height=180. }
    let dan = { Name = "Dan"; Age = 20; Weight = 160.; Height=190. }

    printfn "john result = %b" ((chainOfResponsibility (john, true)) |> snd)
    printfn "dan result = %b" ((chainOfResponsibility (dan, true)) |> snd)

责任链模式的主要功能是由 check函数+函数正向组合运算符>> 实现的,check函数的输入一个处理者函数和一个处理结果,如果已有的处理结果为false则直接返回,否则调用处理者函数更新处理结果。

关于元组的两个操作:

  • fst:返回元组的第一个元素
  • snd:返回元组的第二个元素

命令模式

重做撤消场景的命令模式——原文链接

type Command = { Redo: unit->unit; Undo: unit->unit }

let result = ref 7

let add n = { 
    Redo = (fun _ -> result:= !result + n); 
    Undo = (fun _ -> result := !result - n) }

let minus n = { 
    Redo = (fun _ -> result:= !result - n); 
    Undo = (fun _ -> result := !result + n) }

let cmd = (add 3)
printfn "current state = %d" !result

cmd.Redo()
printfn "after redo: %d" !result

cmd.Undo()
printfn "after undo: %d" !result

注:ref 表示可变引用的类型,使用函数[!]和[:=]以获得和设置此类型的值

另外一种 redo-undo 实现将命令分组在 Do/Undo 类别下,参考 Redo-Undo II 的命令模式。个人觉得对命令分组并不好,每次扩展命令的时候都要改分组部分的代码。

策略模式

根据环境或者条件的不同选择不同的算法或者策略来完成目标功能——原文链接

let quicksort l = 
    printfn "quick sort"
let shellsort l = 
    printfn "shell short"
let bubblesort l = 
    printfn "bubble sort"
type Strategy(sortFunction) = 
    member this.SortFunction with get() = sortFunction    
    member this.Execute(list) = sortFunction list

let strategy() = 
    let s = Strategy(quicksort)    
    s.Execute([1..6])

strategy()

工厂模式

简单工厂模式的实现——原文链接

type IA = 
  abstract Action : unit -> unit

type Type = 
  | TypeA 
  | TypeB

let factory = function
  | TypeA -> { new IA with 
                   member this.Action() = printfn "type A" }
  | TypeB -> { new IA with 
                  member this.Action() = printfn "type B" }

单例模式

饿汉式单例模式的实现——原文链接

type A private () =
    static let instance = A()
    static member Instance = instance
    member this.Action() = printfn "action"

let DesignPatter1() = 
    let a = A.Instance;
    a.Action()

其它内容

剩下的设计模式准备等到视频出来后再转载,后面的Type Provider太过专业很少用到,后面遇到实际应用场景时在学习。

posted @ 2022-09-11 20:13  二次元攻城狮  阅读(107)  评论(1编辑  收藏  举报