1. 什么是函數(shù)式編程?
在我看來(lái)函數(shù)式編程就是把函數(shù)作為一等公民來(lái)使用就是函數(shù)式編程。平常我們開(kāi)發(fā)都是在處理數(shù)據(jù)。面向?qū)ο笾卸荚谔幚眍?。而函?shù)式編程不是在寫(xiě)函數(shù)就是在寫(xiě)函數(shù)的路上。我們來(lái)看看 Java 中函數(shù)式編程的演進(jìn)之路。我小時(shí)候玩過(guò)一種廉價(jià)的黑白屏游戲機(jī),只能玩俄羅斯方塊。這種是不可擴(kuò)展的。
public void playGame(){
// 只能玩俄羅斯方塊
}
這種機(jī)器給童年帶來(lái)了不少的樂(lè)趣。后來(lái)小伙伴有了一臺(tái)gameboy,這種掌機(jī)的好處在于它可以插卡。一張卡一個(gè)游戲,最有名的莫過(guò)于 《超級(jí)馬里奧》 和《打磚塊》了。這時(shí)候機(jī)器是完全可擴(kuò)展的了。
public void playGameboy(GameboyCard card){
card.getGame().run()
}
雖然可以擴(kuò)展但是卡的價(jià)格非常貴,當(dāng)時(shí)買(mǎi)卡的渠道還很少。那時(shí)候其實(shí)就想如果能自己造 gameboy 游戲就好了(然后我就來(lái)搞編程?)。理想中的游戲機(jī)是我們不關(guān)心你什么風(fēng)格的游戲,只要你能放入符合接口的游戲卡中并且在我這個(gè)游戲機(jī)中跑就行。
所以我們定義了一個(gè)固定的游戲卡接口:
/**
* @author Felordcn
* @since 2019/10/31 22:13
*/
@FunctionalInterface
public interface Card {
Game apply();
}
只要符合這種接口的游戲卡都能插到機(jī)器中玩:
/**
* Fun.
*
* @param card the card
*/
void fun(Card card) {
Game game = card.apply();
game.run();
}
熟練面向?qū)ο蟮耐瑢W(xué)們會(huì)說(shuō)這不就是面向接口編程嗎?是的你說(shuō)的沒(méi)有問(wèn)題。但是這里 Card 接口只干一件事就是提供游戲。我們的重心是游戲卡嗎?顯然不是!有趣好玩的游戲才是我們的目的所在。于是我們不管他是卡還是光碟甚至網(wǎng)路,只要能提供游戲給我們娛樂(lè)都符合我們的需要。
// 玩插卡游戲機(jī)
fun(() -> new CardGame());
// 玩 PSP
fun(() -> new PSPGame());
// more
作為一名碼農(nóng),平常我們都在寫(xiě) SQL。無(wú)論大廠小廠,不管單體還是分布式。SQL 總能幫我們解決很多業(yè)務(wù)關(guān)系處理。SELECT、 INSERT、 UPDATE、 DELETE 每一種命令只要是 SQL 規(guī)范數(shù)據(jù)庫(kù),不管是什么表都會(huì)是一致的操作。你聲明了什么命令就執(zhí)行什么操作。這時(shí)數(shù)據(jù)與函數(shù)是松耦合的。正是這樣的特點(diǎn)讓我們實(shí)現(xiàn)了“萬(wàn)變不離其宗”。這也是一種另類的函數(shù)式編程。
2. 面向?qū)ο蠛秃瘮?shù)式編程沖突嗎?
面向?qū)ο笠恢碧幱谖夷懿僮魇裁磾?shù)據(jù)、這種數(shù)據(jù)我該怎么操作的范式中。而函數(shù)式編程一直沉浸于給我操作數(shù)據(jù)的方法中。面向?qū)ο笞畲髢?yōu)點(diǎn)是多態(tài)性和封裝;函數(shù)式編程優(yōu)勢(shì)是抽象化和聲明式命令風(fēng)格,兩者其實(shí)是正交,可互補(bǔ)的,可在同一程序中共存。爭(zhēng)論是面向?qū)ο蠛眠€是面向函數(shù)好跟爭(zhēng)論哪門(mén)語(yǔ)言好一樣都是非常極端的。對(duì)于面向?qū)ο髞?lái)講:存在的并不一定都是對(duì)象,函數(shù)就是對(duì)象;對(duì)于函數(shù)式編程來(lái)說(shuō):存在的并不總是純粹的,副作用總是真實(shí)存在的??傊?,面向?qū)ο髠?cè)重于分解,函數(shù)編程側(cè)重于組合。
3. 函數(shù)式編程特點(diǎn)
函數(shù)風(fēng)格的編程擁有自己的一些特點(diǎn):
函數(shù)作為一等公民。 可以作為參數(shù)傳遞、從函數(shù)里返回、可以賦值給變量。
帶有閉包的 Lambda 表達(dá)式和匿名函數(shù),這是廣泛的多態(tài)。
不變性,大部分無(wú)態(tài)處理,在函數(shù)式程序中,變量是通過(guò)外部傳入或者申明獲得值的。變量不能被改變
基于不可變進(jìn)而可以無(wú)副作用的調(diào)用。
通過(guò) tail call 實(shí)現(xiàn)遞歸的性能優(yōu)化。
提供動(dòng)態(tài)的、可組合的開(kāi)發(fā)思路。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對(duì)作者和來(lái)源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請(qǐng)及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對(duì)此聲明的最終解釋權(quán)。