内容简介:Proxy Pattern 是 OOP 中著名的 Design Pattern,尤其可在不改變 interface 的前提下,就能控制該物件的使用,F# 既然是 Function First Language,就讓我們以 function 的角度重新實現 Proxy Pattern。macOS High Sierra 10.13.3.NET Core SDK 2.1.101
Proxy Pattern 是 OOP 中著名的 Design Pattern,尤其可在不改變 interface 的前提下,就能控制該物件的使用,F# 既然是 Function First Language,就讓我們以 function 的角度重新實現 Proxy Pattern。
Version
macOS High Sierra 10.13.3
.NET Core SDK 2.1.101
JetBrains Rider 2017.3.1
F# 4.1
User Story
假設你在處理訂單,只有會員才能享受 全館八折
,其他人都只能原價購買。
- 目前已經有
MemberService.isMember()
判斷是否為會員 - 目前已經有
OrderService.getPrice()
可根據折購計算售價 - 在
MemberService.isMember()
與OrderService.getPrice()
不修改的前提下 (開放封閉原則
),計算出售價
Task
直接使用 FP 的思維完成需求。
Definition
Decorator Pattern
在不改變原有 interface 的前提下,控制 service 的使用
首先思考 Proxy Pattern 的本質:
- Proxy 與 RealSubject 之間的 interface 必須相同
- Client 藉由 Proxy 控制 RealSubject 的使用
只要能達到這兩個目標,就算完成了 Decorator Pattern。
OOP 思考方式
- 為了讓 Proxy 與 RealSubject 的 interface 要相同,所以必須訂出共同的 interface
- Proxy 必須以 state 記住 RealSubject,client 才能透過 Proxy 使用 RealSubject
- Proxy 可以加上邏輯,控制 RealSubject 的使用
FP 思考方式
- Proxy 與 RealSubject 都是 function,不用事先定義 interface,反正只要 interface 不同,在
if … else
、Pattern Matching
或try catch
一定會錯 - Proxy 與 RealSubject 都是 function,既然 interface 都相同,由 RealSubject 切換到 Proxy 就不用修改程式碼
- Proxy function 可加上邏輯,控制 RealSubject function 的使用
Implementation
MemberService.fs
namespace MemberLibrary module MemberService = let isMember account = account = "Sam"
isMember()
判斷是否為 會員
。
實務上判斷 是否為會員
與資料庫有關,本文主要是談 Proxy Pattern,就只簡單的判斷會員是否為 Sam
即可。
OrderService.fs
namespace OrderLibrary module OrderService = let getPrice discount price = price * discount * 1.0
計算 全館八折
,之所以加上 * 1.0
,是為了讓 Type Inference 推導出 discount
與 price
的型別為 float
。
當使用 function pipeline 時,最後一個參數可以自動被 pipeline,所以設計 function parameter 時,將要使用 pipeline 的 value 放在最後一個 parameter,才能發揮 pipeline 的優勢
Program.fs
open MemberLibrary open OrderLibrary open System [<EntryPoint>] let main argv = let account = "Sam" let originalPrice = 800.0 let discount = 0.8 let isMember = MemberService.isMember account let orderProxy = match isMember with | true -> OrderService.getPrice | false -> fun _ price -> price originalPrice |> orderProxy discount |> printf "Real price : %0.0f" 0 // return an integer exit code // Real price : 640
11 行
let isMember = MemberService.isMember account
由於會由 MemberService.isMember()
判斷是否為會員,先判斷並將結果 binding 到 isMember
。
13 行
let orderProxy = match isMember with | true -> OrderService.getPrice | false -> fun _ price -> price
將 OrderProxy
class 退化成 orderProxy()
function,其 interface 仍然為 float -> float -> float
,Type Inference 會自動推導,若有違反,Pattern Match 就會報錯。
orderProxy()
本質為 function,由於 closure 機制,可以自然使用到 function 外面的 isMember
,因此不必使用 parameter 方式傳入。
Pattern Matching 根據 isMember
結果回傳 OrderService.getPrice()
,或者全新的 Lambda function。
| false -> fun _ price -> price
由於要 return 的 Lambda function 並沒有使用到 discount
計算,使用 _
代表即可。
16 行
originalPrice |> orderProxy discount |> printf "Real price : %0.0f"
將 originalPrice
傳給 orderProxy()
計算,這是個已經考慮 是否為會員
的 orderService()
,最後再傳給 printf()
顯示。
Summary
回想 Proxy Pattern 的本質:
- Proxy 與 RealSubject 之間的 interface 必須相同
- Client 藉由 Proxy 控制 RealSubject 的使用
雖然沒有特別定義 interface,但 orderProxy()
與 OrderService.getPrice()
的 signature 都是 float -> float -> float
,若 function 的 signature 不同,在 Pattern Matching 就會編譯錯誤,與原本 Proxy Pattern 定義 interface 的本質相同。
FP 則藉由 Proxy Function 控制 RealSubject function 的使用,與原本 Proxy Pattern 藉由 Proxy 控制 RealSubject 使用的本質相同。
Conclusion
- Proxy Pattern 本質就是 delegation,但 object 的 delegation 沒 function 簡單直覺,所以才需要搭配 interface;但若純 function,連 interface 都不需要,而且也能享受 strong type 的編譯檢查
Sample Code
完整的範例可以在我的 GitHub 上找到
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- RecyclerView使用指南(一)—— 基本使用
- 如何使用Meteorjs使用URL参数
- 使用 defer 还是不使用 defer?
- 使用 Typescript 加强 Vuex 使用体验
- [译] 何时使用 Rust?何时使用 Go?
- UDP协议的正确使用场合(谨慎使用)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP+MySQL八大动态Web应用实战
Jono Bacom / 吴连河、李剑 / 电子工业出版社 / 2008-6 / 68.00元
本书详细介绍了利用PHP+MySQL开发常见类型Web应用程序的完整设计和编码技术,并对整体设计与关键代码给予了细致、深入的剖析。其内容注重实践,提供了翔实完整的实战代码;思路独树一帜,突破过多描述语言细节的窠臼;行文风趣幽默,轻松调侃中将项目的完整设计过程分析得一清二楚。书中的示例项目完整而实用,读者甚至无需任何改动即可在实际中加以运用。. 本书适合对PHP/MySQL有初步了解但缺乏完整......一起来看看 《PHP+MySQL八大动态Web应用实战》 这本书的介绍吧!