對rxjava實現(xiàn)思想的個人思考

這篇文章不是講解rxjava如何使用,而是對其設(shè)計的思考。
使用過rxjava的同學(xué)們都注意到rxjava的操作符很多很多,具體有多少?


Rx的部分操作符截圖.png

對于這么多的操作符,如果作為大多數(shù)的我們而言,由我們來設(shè)計,當(dāng)然是針對不同的操作符實現(xiàn)自己的邏輯即可咯。但是實際情況當(dāng)然不是這么簡單,rx操作符只要不是最終執(zhí)行subscribe訂閱,操作符是可以無限制切換調(diào)用的,例如.just(...).map(...).filter(...).take(...).map(...),只要你想調(diào),你就可以一直調(diào)下去。

問題1:為什么要設(shè)計成操作符可以無限切換?

這個其實不難理解,基本就是為了達(dá)到業(yè)務(wù)處理的靈活性。

試想一下,如果操作符間不能隨意切換,做完一件事就結(jié)束了,那我們?yōu)槭裁匆啻艘慌e要用rxjava,還不如我們不用,完全可以直接寫業(yè)務(wù)代碼的嘛。

所以,這里就引出了rxjava的事件流的概念,每調(diào)用的一個操作符都是事件流的一部分,從上流可以一直流到下流直到結(jié)束,或者中途異常中斷或跳過處理等等。這就好比使用app買門票一樣,會有個注冊 -> 登錄 -> 買門票的流程,流程一切正常,ok,門票購買成功,否則就是不成功。

對于該種設(shè)計的優(yōu)點,我個人認(rèn)為主要有以下幾點:

  • a、對于多種業(yè)務(wù)地獄式回調(diào),使用rx則可以免去這些回調(diào),使用官方的語言就是響應(yīng)式編程。其好處就是代碼更加直觀,減少維護(hù)成本;

  • b、更靈活的業(yè)務(wù)處理。
    這點很重要,例如由于版本迭代,某個版本突然產(chǎn)品經(jīng)理要加某個功能點,但隨著代碼設(shè)計復(fù)雜度的提升,改動特別麻煩。但是rxjava的方式,或許就是再額外加個操作符的事情,其不僅僅是增加方便,刪除也很方面,或許就是刪除指定操作符調(diào)用而已。

  • c、解耦不同業(yè)務(wù)間的耦合。
    從上班的那天起,耦合便無時無刻不伴隨我們身邊。優(yōu)秀的代碼,不少都是耦合度很低的代碼。為什么很多時候我們都不愿意看別人的代碼?不僅僅是編碼習(xí)慣的不同,耦合的問題也是我們不愿看別人代碼的一部分原因,誰都不愿意看到所有業(yè)務(wù)糅合在一塊的垃圾代碼吧。
    但是我們該如何通過rxjava解耦?當(dāng)然也是可以從操作符上邊下功夫了。具體業(yè)務(wù)只做一件事情,對應(yīng)一個操作符,盡量做到細(xì)粒度(當(dāng)然了,有時候還要具體情況具體對待)。

問題2:如何做到操作符的無限切換?

試想一下,如果是由我們自己去設(shè)計一套類似rxjava操作符,我們該如何實現(xiàn)呢?
是不是要在每個操作符內(nèi)部還要判斷當(dāng)前操作符之前是否加入過其他操作符,如果加入過,還要處理其他操作符的邏輯?

如果隨著業(yè)務(wù)的不斷增長,又要加入其他操作符,難道我們每次都要改動所有操作符內(nèi)部實現(xiàn)?

以上兩種處理方式當(dāng)然是不切合實際的?當(dāng)你已走上這種道路,其實你開始就已經(jīng)給自己今后挖坑了,而且這種坑是會無限制的放大,懂了吧。

也就是說上面的方式是通過強耦合的方式實現(xiàn)的,既然如此,如何免去耦合,還能靈活的完成各操作符自有邏輯?

有人可能會想,又想實現(xiàn)現(xiàn)有功能,又不想影響其他功能,哪有這種好事???實話告訴你,還真的有,而且必然有,這些思想都是前人走過來并且總結(jié)的經(jīng)驗。這些經(jīng)驗大多都在設(shè)計模式之中有所體現(xiàn),這也正是設(shè)計模式魅力的體現(xiàn),但也不能因模式而模式。

現(xiàn)在轉(zhuǎn)變下思路,如果將每個操作符都想象成一種咖啡,現(xiàn)有濃縮咖啡,瑪琪雅朵,美式咖啡,白咖啡,拿鐵咖啡,并且假如每種咖啡都可以隨意組合,以符合不同人的口味,無論哪種咖啡,它都是咖啡,當(dāng)把他們隨意組合之后,難道他們就不再是咖啡了嗎,當(dāng)然還是。無論你想喝哪種組合的咖啡,我當(dāng)然不會蠢到每次都一個一個的定制,因為有現(xiàn)成的咖啡,組合一下就可以了嘛。大家想到了嗎?這正是裝飾模式。

裝飾模式實在是太強大了,實在是無法說其到底有多好,哈哈。無論你產(chǎn)品經(jīng)理如何提需求,在整體邏輯類似的情況下,我就只需要再掏出一個指定邏輯的裝飾器即可。rxjava也正是用到了這種思想,每當(dāng)你切換一個操作符,其實對他而言也就只不過是在前一個裝飾器基礎(chǔ)上再額外添加當(dāng)前一個裝飾器而已,在發(fā)布訂閱后,當(dāng)前裝飾器執(zhí)行完畢后,再讓上一個裝飾器去執(zhí)行其自己邏輯,以此類推。

下邊以一個簡單的字符串小寫轉(zhuǎn)大寫,并配合其具體流程圖+類圖來加深對rxjava的印象:

fun doWithMap() {
    Observable
            .create<String> {
                it.onNext("abc")
            }
            .map {
                it.toUpperCase(Locale.ROOT)
            }
            .subscribe {
                L.e(it)
            }
}

該實現(xiàn)對應(yīng)的大致rx執(zhí)行流程圖為:


rxjava從create到map再到訂閱的過程.png

以O(shè)bservableCreate為例的類圖(由于Observable系列的裝飾類實現(xiàn)大同小異,故單以其中的ObservableCreate為例):


以O(shè)bservableCreate為例的類圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容