響應式程式設計的思維藝術 (2)響應式Vs物件導向

2022-01-10 08:39:36 字數 3771 閱讀 8358

本文是rxjs 響應式程式設計-第一章:響應式這篇文章的學習筆記。

目錄三. 響應式程式設計實現

四. 差異對比

三句非常重要的話:

原文對很多基礎卻核心的概念都有詳細的講解,本文不再贅述。需要注意的是,理解原理是一方面,但能夠熟練使用運算子來轉換或查詢流資訊是需要很長時間積累的,建議在學習過程中,每次遇到新的運算子就主動查閱資料理解其用法,這樣積少成多慢慢地就總結出開發模(tao)式(lu)了。

為了更直觀地感受物件導向和響應式程式設計中的不同,筆者分別用兩種模式實現了兩個一樣的小動畫,demo比較簡單,就是乙個不斷奔跑的角色和乙個無限滾動的背景圖。但是就體會和理解兩種開發模式而言基本夠用了。

動畫例項使用canvas畫布來完成,簡單動畫的基本程式設計模式如下:

//啟動函式

function startcanvasanimation()

//每個繪製週期重複呼叫的繪製函式

function paint()

return requestanimationframe(paint);//尾遞迴呼叫繪製函式

}

當然示例中沒有涉及區域性更新或其他有關渲染效能的部分,更複雜的動畫需求可以直接使用引擎來實現,這不是本篇的重點。

/**

* 角色類

*/class role

//更新自身狀態

update()

}//繪製

paint()

}

背景也可以當做是乙個精靈動畫例項,以同樣的模式定義即可,示例中的角色並沒有實現相對畫布的運動(也就是視差),感興趣的讀者可以自己嘗試實現,完整的示例**見附件。

物件導向程式設計中,具體的精靈類可以繼承抽象精靈類,且將具體的實現封裝在自己的類定義中,最後使用類似於建造者模式的方法將各個例項組織起來,有物件導向程式設計經驗的讀者對這個流程應該不會陌生。

在響應式程式設計中,我們需要構建角色動畫流背景動畫流這兩個可觀測物件,然後將這兩個流合併起來,此時就得到了乙個尚未啟動的動畫資訊流,通過subscribe( )方法啟動這個流,並將繪製方法傳入**函式,就可以實現乙個同樣的動畫了。

/**動畫的rxjs響應式程式設計實現*/

//定義動畫幀率

var rxjsratio = 50;

var rxjsframe = parseint(1000/rxjsratio,10);

//構建角色動畫流

var rolestream = rx.observable.interval(rxjsframe).map(i=>});

//構建背景動畫流

var bgistream = rx.observable.interval(rxjsframe).map(i=> i%800);

//合併流

var rxjsanim = rx.observable.combinelatest(rolestream,bgistream,(role, bgi)=>

}).subscribe(rxjsrender);

//繪製角色

function rxjspaintrole(rolepos)

//繪製背景

function rxjspaintbgi(offset)

//繪製

function rxjsrender(actors)

物件導向程式設計用類和繼承封裝多台來聚合關係,響應式程式設計用流和變換來聚合資訊。

通過**對比可以發現,在響應式程式設計中,我們不再用物件的概念來對現實世界進行建模,而是使用的思想對資訊進行拆分和聚合。在物件導向程式設計中,資料資訊資料更新方法繪製方法這三大要素都是描述具體類的,他們被類的定義聚合在了一起;而在響應式程式設計中,不再強調「關係」,而是將資料和變化聚合在一起,將處理方式聚合在一起。試想假如上面的示例中增加不同的類,障礙,怪物,積分等等,那麼物件導向程式設計中就需要增加新的類定義,而響應式程式設計中就需要增加新的資料流,但是在每乙個繪製的時間點拿到的暫態資料和根據這些暫態資料進行的繪製動作,其實都是一致的,區別只是關鍵資訊的聚合方式不一樣了

在傳統程式設計中,我們常常會得到乙個無法直接用於最終場景的資料集合,然後需要手動做一些後處理,最終把生成可被使用的資料提供給消費模組;而響應式程式設計中強調的,是「直接告訴程式你最終想要獲得什麼資料」,然後將程式的加工流程內化到生產過程中,從而當消費模組得到資料時,直接就可以使用,而不需要再做更多的後處理,這對於消費者來說無疑是體驗的提公升,就好像你去買組裝電腦時,商家都會幫你推薦元件送貨上門還會幫你組裝好,你肯定感覺服務很到位,因為大部分人的目的是使用電腦,而不是享受買電腦的過程。

如果說物件導向程式設計思想是在描述客觀世界,那麼響應式程式設計就更像是在嘗試揭示規律。

回過頭再來看我們上面實現的demo,在傳統的程式設計中,我們的思維模式更加傾向於一種微積分的思想,也就是說我們試圖描述乙個精靈動畫的變化時,關注的是如何從x[i]得到x[i+1],當我們得到這樣乙個變換方法x[i+1]=g(x[i])後,只需要在物件的屬性中記錄每乙個時刻的x[i],然後在下乙個繪製週期開始時執行這個方法計算出x[i+1],按照新的值繪製元素,用新值覆蓋舊值,然後迴圈這個過程就可以了;而在響應式程式設計中,我們採取的方式是為x[i]求出乙個通項公式,也就是x = f(i)這樣一種數學形式的描述,它們之間的關鍵區別並不是函式體內邏輯的表達形式,而是在物件導向中實現的方法是有狀態的(你需要用某個例項屬性來標記幀動畫例項當前的執行狀態),而響應式程式設計中的方法是無狀態的,是不是聯想到什麼了?沒錯,函式式程式設計中的純函式。響應式程式設計本來就是建立在函式式程式設計基礎之上的,只通過純函式實現集合的對映變換。

如果你聽說過傅利葉變換,應該不難發現響應式程式設計的思維模式和它很像,傅利葉變換可以將乙個混雜的訊號,拆分成若干個不同振幅頻率和相位的正弦波的,這樣工程師就可以獨立分析自己感興趣的部分,這是訊號分析中很基本的手段。在響應式程式設計中,系統中的狀態變化以類似的方式被拆分成了很多獨立的流,如果開發者關注的某個流出現異常,只需要單獨關注其資料來源和用於流變換的函式鏈即可(當然它的資料來源也可能會被拆分成若干個獨立的流),而不必陷入巨大的邏輯關係網,這對於提公升大型系統的除錯效率來說是非常重要的。在物件導向程式設計中,這一點是很難做到的,更常見的情況是你修改了a方法,然後b方法就報錯了,緊接著你發現這個過程竟然是遞迴的,最後程式崩潰了,你也崩潰了。

筆者只是初學,對響應式程式設計談不上什麼經驗,但程式的世界裡終究是「沒有更好的技術,只有更適合的方案」,在合適的場景做到合適的技術選型才更重要,至於什麼樣的場景更適合響應式程式設計,還需要在後續的學習和實踐中慢慢體會,但無論如何,響應式程式設計中蘊含的工程思想和數學之美讓我讚嘆。

響應式程式設計 什麼是響應式程式設計

那麼什麼是響應式程式設計,來看個簡單的例子 var i 1,j 2,k i j print k k k 3 i 3 j 4 print k k k 3在這裡把i,j,k當成某個狀態,k是j,i兩個狀態的組合,正常的程式設計中,在計算了k的狀態之後,再去改變j,i的狀態是不會影響到c的狀態的。所以在正...

響應式程式設計

react中提出乙個重要思想 狀態改變則ui隨之自動改變,而react框架本身就是響應使用者狀態改變的事件而執行重新構建使用者介面的工作,這就是典型的響應式程式設計正規化,下面我們總結一下react中響應式原理 開發者只需關注狀態轉移 資料 當狀態發生變化,react框架會自動根據新的狀態重新構建u...

響應式程式設計(一)什麼是響應式程式設計

響應式程式設計是相對於阻塞式程式設計,我們在這裡主要講的是springboot2中響應式webflux 了解 webflux,首先了解下什麼是 reactive streams。reactive streams 是 jvm 中面向流的庫標準和規範 處理可能無限數量的元素 按順序處理 元件之間非同步傳...