如何使用 F# 實現 Decorator Pattern?

栏目: ASP.NET · 发布时间: 7年前

内容简介:Decorator Pattern 是 OOP 中著名的 Design Pattern,尤其可在不改變 interface 的前提下,動態對原有物件增加功能,F# 既然是 Function First Language,就讓我們以 function 的角度重新實現 Decorator Pattern。macOS High Sierra 10.13.3.NET Core SDK 2.1.101

Decorator Pattern 是 OOP 中著名的 Design Pattern,尤其可在不改變 interface 的前提下,動態對原有物件增加功能,F# 既然是 Function First Language,就讓我們以 function 的角度重新實現 Decorator Pattern。

Version

macOS High Sierra 10.13.3

.NET Core SDK 2.1.101

JetBrains Rider 2017.3.1

F# 4.1

User Story

假設你在處理訂單,訂單的折扣方式有兩種

  • 超過 1000 元,則 全館八折滿千送百
  • 不到 1000 元,則 全館八折

Task

直接使用 FP 的思維完成需求。

Definition

Decorator Pattern

在不改變原有 interface 的前提下,動態增加原有的功能

如何使用 F# 實現 Decorator Pattern?

首先思考 Decorator Pattern 的本質:

  1. Component 與 decorator 之間的 interface 必須相同
  2. Component 可自由組合 decorator

只要能達到這兩個目標,就算完成了 Decorator Pattern。

OOP 思考方式

  • 為了讓 component 與 decorator 的 interface 要相同,所以必須訂出共同的 interface
  • 由於 decorator 必須包含原本 component 功能,因此 decorator 必須以 state 方式保存原本 component
  • 由於各 decorator 都必須透過 constructor 保存原本 component,因此將共用 constructor 抽出來由 AbstractDecorator 實作

FP 思考方式

  • Component 與 decorator 都是 function,不用事先定義 interface,反正只要 interface 不同,在 Pattern Matching 一定會編譯錯誤
  • Component 與 decorator 都是 function,既然 interface 都相同,只要是用 Function Composition 產生新的 function 即可

Implementation

PriceDecorator.fs

namespace OrderLibrary

module PriceDecorator =  
    let discountPrice price = price * 0.8
    let rebatePrice price = price - 100.0

discountPrice() 表示 全館八折

rebatePrice() 表示 滿千送百

由於 component 與 decorator 基本上都是 double -> double 的型別,可以廣義視為 decorator。

OrderService.fs

namespace OrderLibrary

open PriceDecorator

module OrderService =
    let getPrice price = 
        match (price > 1000.0) with
        | true -> (discountPrice >> rebatePrice) price
        | false -> discountPrice price

根據商業邏輯:

超過 1000 元,則 全館八折滿千送百

因此將 discountPrice()rebatePrice()>> compose 成一個新的 function,就相當於 全館八折滿千送百

在 FP 只要使用 Compose Function,就相當於 OOP 的 Decorator Pattern,在 F# 只需 >> ,但 C# 卻要 interface 與 abstract class 的搭配才能實現

Program.fs

open System
open OrderLibrary

[<EntryPoint>]
let main argv =
    1200.0
    |> OrderService.getPrice
    |> printfn "%f"
    
    800.0
    |> OrderService.getPrice
    |> printfn "%f"
        
    0 // return an integer exit code

將各種 price 以 Pipeline 方式傳給 OrderService.getPrice() 計算,並將結果傳給 printfn() 顯示。

Summary

回想 Decorator Pattern 的本質:

  1. Component 與 decorator 之間的 interface 必須相同
  2. Component 可自由組合 decorator

由於 component 與 decorator 的 interface 相同,可以廣義視為 decorator,雖然沒有特別定義 interface,但 discountPrice()rebatePrice() 的 signature 都是 double -> double ,若 function 的 signature 不同,在 Pattern Matching 就會編譯錯誤,與原本 Decorator Pattern 定義 interface 的本質相同。

原本 OOP 的 Decorator Pattern 可以透過 new 自由組合 decorator object,但 FP 可透過 >> 自由組合 decorator function,與原本 Decorator Pattern 的自由組合 decorator 本質相同。

Conclusion

  • Decorator Pattern 本質就是 object 的組合,但 object 的組合沒 function 簡單直覺,所以才需要搭配 interface 與 abstract class,但若純 function,只要使用 Function Composition 即可簡單完成

Sample Code

完整的範例可以在我的 GitHub 上找到


以上所述就是小编给大家介绍的《如何使用 F# 實現 Decorator Pattern?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

一本书读懂24种互联网思维

一本书读懂24种互联网思维

安杰 / 台海出版社 / 2015-3-1 / 39.80元

互联网思维已经不再局限于互联网,与当初人类史上的“文艺复兴”一样,这种思维的核心即将开始扩散开去,对整个大时代造成深远的影响。本书是深入研究互联网思维的精华之作,作者深入浅出地集中阐述了24种互联网思维的内核与精神,并结合实例对这24种互联网思维逐一进行了点评。对于个人与企业如何抓住互联网思维背后正喷薄而出的工作、生活、商业上的大革新与大机遇,如何在互联网思维下进行运作,如何运用互联网思维进行升级......一起来看看 《一本书读懂24种互联网思维》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具