上次隨便一吐,發現挺多共鳴的,好吧,今天我來吐一吐亂用注入。
注入是個很裝逼的詞語,java對這個詞解釋的神鬼都怕,高級裝逼直的人稱ioc,di什么的,入行淺的人看着高深,其實就是給對象屬性賦個值而已。學術界的老師教授等人就喜歡搞這種東西,用十個你沒聽過的詞來解釋一個你沒聽過的詞,說得太明白怕你們知道他不懂怎么辦。好像吐錯方向了,下面直接說正題吧。
舉個例子,A界面打開B界面,B界面點擊個按鈕后需要A界面做些反應。有些人給出下面這個方案。A構造出B的時候把A的一個函數傳給B,B操作完回調A。我先不否定,如果是做彈窗回調,這樣做是沒問題的。
下面我再說一個復雜一些的,A界面打開B界面打開C界面,然后函數從A傳到了C,不僅如此,D需要用到C,也傳反射函數到C。那么問題來了,你寫代碼的時候,發現C對象里面有一個函數變量,你要找出這個函數是從哪里注入(賦值)進來的。全局查到BD都有可能會注入,糾結了吧,還得先把BD給讀一下看能不能改。
再說一個更坑爹的,你的需求變了,你需要修改C,好吧,可以開噴了。我只想改C,結果我不得不把AB和C都讀一下看能不能改。如果是把一個接口從A傳到C還算是幸運的,起碼知道接口里面有什么,但是有很多過份的做法是把一個反射函數傳他個五六七八次。這時候策划來一需求要改這五六七八次的其中一次,這種技術員就開始罵策划了。
可能上面說例子有點腦亂,我再說一個寫前端的人肯定會碰到過的,父類界面A傳一個參數給子界面B,子界面B又傳給子界面C。最下層的C界面操作完了,父類A界面發生改變。一種很糟糕的做法是把A的函數傳到C,給C調用。當別人讀碼的時候,找這個函數從哪里傳來的,要把這一條長長傳遞鏈全部往上找一遍,這條鏈只要有一個需求改了,修改就痛苦了。然后又有人給出了下面這個方案。界面A設成單例,C調用A單例執行他的方法,這個方案是解決了可讀性,但是帶來另外的問題,所有界面都搞成單例就意為着無法繼承復蓋,無法用上篇文章我說的解耦方法,而且界面A不能多開,還有個問題就是所有界面全占着內存無法釋放。
好吧,噴歸噴,下面說說解決方案。有經驗的人早就想到了,那就是用事件。子界面發個事件給A接收就行了,不管A到Z經過了次傳遞,Z要讓A反應只有一級。有人會說,Z想要用A的數據怎么辦?解決方案是把數據做成單例,不管A里面有多少子項,各子項都是自己從數據單例里拿數據自己解析自己,就算一個界面的子項有幾個人寫,這幾個人寫的東西也不需要修改別人的代碼來完成自己的邏輯(除了入口),MVC解耦就是這個思路。當然特例也是有的,例如列表父項要讓子項的位置變化,什么時候碰到讓我抓狂受不了的事件亂用再吐吧。
下面說些復雜的,因為數據是從服務端過來,或者從數據庫過來,並不會像界面那樣需要繼承,也不會像界面那些占用這么多內存。所以數據做成單例也不會有什么性能問題。有人說用了設計模式會浪費性能,也不知道這些沒經驗人的從哪來的這個結論。不用模式亂傳參,傳他五六七八次然后回調,跟監聽者模式發一次事件相比,性能誰好,一目了然。有人說用模式會多寫很多代碼,做前端的,不管你什么項目都有界面,有數據。不用模式的其實就是把數據和界面寫到一個類,用模式就是分開兩個類來寫,代碼量有變多嗎?參數一級級傳遞和只用一個事件相比,哪個代碼量多?只是亂用才會多廢代碼吧。
曾帶過的小弟讀亂用模式的代碼說,看不懂,但是感覺好高深……其實不用自卑,看不懂的代碼不是讀的人的問題,是寫的人有問題。我曾拿一套很有經驗的代碼給小弟讀,小弟說,就這樣啊,這么簡單粗暴。自己也是從新手過來的。對這種胡亂崇拜有說不出的味道。