面向過程,物件導向,函式式對同乙個問題的思考方式

2021-09-07 03:08:08 字數 2942 閱讀 3979

我之所以對函式式**感興趣是因為函式式**富有表現力,可以使用簡短、緊湊的**完成工作,同時能對特定的問題給出優雅的解決方案。現代的程式語言不約而同的朝著物件導向、函式式、動態、解釋執行的方向發展,例如ruby,swift。而另一些語言則更加強調函式式程式設計,如f#,scala,這種語言有著強大的型別推斷系統,編寫的**潔程度則令人嘆為觀止。

在f#編寫乙個兩個數相加的函式,在f# interactive中輸入:

let add num1 num2=num1*num2;;
f# interactive為我們推斷了這個函式型別:val add : num1:int -> num2:int -> int,表示add有兩個int型別的引數得到了1個int型別。

函式當作引數:

//c#

private int twice(int input,funcf)

var result = twice(2, n => n*n);

使用f#則只需要非常簡潔的乙個函式宣告:

> let twice (input:int) f=f(f(input));;

val twice : input:int -> f:(int -> int) -> int

> twice 2 (fun n->n*n);;

val it : int = 16

val twice : input:int -> f:(int -> int) –> int 這句話則是f# interactive給出的推斷:twice函式需要乙個int引數和乙個(int->int)的函式作為引數,返回乙個int.

這兩個例子僅僅是熱身,並不是本篇部落格的重點,所以你覺得前兩個例子很無聊或者沒太看明白請繼續看下面的總結。

場景:某種活動會有乙個日程安排(schedule),日程安排有3中型別,只舉辦一次(once),每天一次(daily),每週一次(weekly)。活動會根據日程安排(schedule)的型別不同具有不同的宣傳內容,不同的延期舉行策略。

你對於這樣的場景會有怎麼樣的思考呢?

一、面向過程型別的編碼方式

面向過程型別的編碼是需求的直譯過程,**會寫成這樣:

1.顯示活動的宣傳內容:

public void showscheduledescriptions()

}

這樣的**初次看起來沒什麼問題,實際存在兩個危險訊號:

2. 延期活動:

public void delayschedule()

}

這樣的代格違反了dry原則,相同的**框架卻無法重用。

二、物件導向的編碼方式

對於乙個有經驗的oo開發者,一旦看到switch,if(type=typeof(…))之類的**馬上會提高警惕,是不是有一些抽象型別沒有被找出來?在這個例子中則會找出下面的抽象:

public  class schedule

public virtual void delayschedule()

}public class onceschedule : schedule

public override void delayschedule()

}public class dailyschedule : schedule

public override void delayschedule()

}//... other schedule

這樣的**很好的解決了面向過程**的兩個問題,看起來更加具有擴充套件性,隨著新型別的schedule引入,舊的**完全不用改動。

當然事情也不是絕對的,什麼情況下需要改動舊**呢?當需要擴充套件schedule的行為的時候,例如需求公升級,不同的schedule具有不同的舉辦方式,我們不得不在每種schedule中加入乙個 void hold()方法。

三、函式式解決方案

函式式語言則使用可區分聯合和模式匹配來處理此類問題。

定義乙個schedule可區分聯合:

type schedule=

| once of datetime

| daily of datetime*int

| weekly of datetime*int

這個型別既說明了schedule有三個不同的型別,同時定義了三種型別分別具有的資料結構。像是enum和類的綜合體,但是又顯得特別精緻。

1.顯示活動的宣傳內容,使用了模式匹配:

let showshowscheduledescriptions schedule=

match schedule with

| once(datetime)-> printfn "this is once activity"

| daily(datetime,int)->printfn "this is daily activity"

| weekly(datetime,int)->printfn "this is weekly activity"

這個方法類似於switch…case,但是通過匹配可區分聯合來實現,而不是通過乙個顯示的enum來實現。

2. 延期活動:

let delayschedule schedule=

match schedule with

| once(datetime)-> printfn "delay one hour"

| daily(datetime,int)->printfn "delay one day"

| weekly(datetime,int)->printfn "delay one week"

函式式程式設計的解決方案認為可以很方便的新增新的行為,例如增加新的行為:hold()。通過定義可區分聯合和模式匹配來完成編碼,整個解決方案像是面向過程和物件導向的一種結合體,但是側重點不同,實現的**也更加精緻。

面向過程,物件導向,函式式對同乙個問題的思考方式

我之所以對函式式 感興趣是因為函式式 富有表現力,可以使用簡短 緊湊的 完成工作,同時能對特定的問題給出優雅的解決方案。現代的程式語言不約而同的朝著物件導向 函式式 動態 解釋執行的方向發展,例如ruby,swift。而另一些語言則更加強調函式式程式設計,如f scala,這種語言有著強大的型別推斷...

物件導向 同乙個需求 五種開發方式

計算器 加法,減法。版本1 用函式庫開發演算法 操作 定義mymath1類 定義靜態加法 int add int,int 定義靜態減法 int sub int,int.main方法中呼叫。版本2 用定義類的方法 定義mymath2類 定義兩個私有成員 int num1,intnum2。定義非空建構函...

乙個物件,兩個物件,同乙個物件的記憶體解析

1.首先我們知道方法區放的是.calss檔案 所以 phone.calss he demo01phoneone.calss出現在方法區,2.然後當方法要執行的時候首先需要進棧這時候main 方法進棧 宣告了乙個區域性變數 phone one 3.我們,我們又知道方法堆中放的是new出來的,所以 ne...