iOS架構設計解耦的嘗試之??榧渫ㄐ?/div>

隨著系統內部邏輯單元(可能是???,也可能是為了解耦拆解出來用來承載職責的類等常見的實現)的增多。勢必會引入另外的一個問題,就是邏輯單元之間的交互增加和邏輯單元之間通信成本的提高。在iOS架構設計系列之解耦的嘗試之變異的MVVM,一文中我們在將整個業務邏輯層從MCV向MVVM演變的時候也遇到了這個問題,當時是本著作孽自己造輪子的心態,通過構建EventBus組件來解決。同樣,針對于邏輯單元之間通信成本增加的問題,也需要尋找一個合適的解決方案。

問題場景描述

香港彩票透码 www.kptln.icu 在ios多??楣芾硪晃鬧?,描述一種進行系統??椴鸞夂凸芾淼乃悸?。將職能不同的業務,拆解成了獨立的???。而且每個??橥ü敫衾?,做到了互相之間影響的最小化。但是他們之間怎么交互呢?換種說法就是業務??橛Ω帽┞┦裁囪耐獠拷涌?以方便其他業務??槔吹饔??

在終端上業務邏輯主要是圍繞著界面展開的。在iOS中的表現就是各式各樣的ViewController。而在以往的編碼實踐中,所謂業務??榧淶慕換ゾ褪荲C之間的相互調用。我們常見的是這樣的:

UIViewController* aVC = [UIViewController new];
//配置aVC需要參數
....
[self.navigationController pushViewController:aVC animated:YES];

或者這樣的

UIViewController* aVC = [UIViewController new];
//配置aVC需要的參數
...
[self presentViewController:aVC animated:YES];

我們通過對于指定業務??櫚拇爰兌美吹饔枚苑降姆?。而這種依賴屬于接口依賴,稍微符合接口隔離的設計。但不是一個符合迪米特法則(最小知識法則)的設計。調用方由于對于服務提供方有接口依賴,因而就造成了以下的潛在問題:

  1. 鏈接過程中必須引入服務提供方所在的???,無法提供打包過程中動態下掉某些業務??櫚男棖?。

  2. 服務提供方類接口變動,將直接調用方。

  3. 調用方知道了服務提供方的太多有冗余信息。

這些問題,我們通過代碼級別的??楦衾牖舊轄餼雋?。正如前文所說,你要真正把??櫓淶慕換ビ跋旖檔偷淖钚?,最好的解決方案就是建造『信息孤島』,而信息孤島就會造成??櫓洹杭θ轡爬纖啦幌嗤礎?,這也非我等所愿。他們之間還要保持一個最小的通信,來完成服務的調用。這樣我們在代碼隔離之后,就要解決兩個問題:

  1. ??櫸⑾?,就是說我一個??樵趺幢黃淥?櫸⑾?,或者說我一個??樽魴┦裁詞慮?,外部??槭褂玫氖焙?,才能知道有我的存在。

  2. 服務調用,??樽鑫裉峁┓?,需要能夠真實的提供所標稱的服務。

機制與策略分離

解決這兩個問題,我們首先要說一個觀點就是機制與策略分離。我們希望設計的是一整套能夠滿足上述要求的協議,其次才是實現,最后才是在我們的APP中的具體應用。這也是我這一年來的一個非常重要的總結。并且在逐漸開源出來的一些庫中也體現著這個設計。具體說一下,所謂機制即是抽象出來的規則,比如:

f(x)=x^2 x屬于R

所謂策略即是在具體場景中的應用,比如當x=2的時候:

f(2)=4 x=2

很明顯剛才說的三個層次中協議與實現做成了一個機制與策略分離。而實現與應用又組成了另外的一個機制與策略分離。我比較喜歡這種嵌套的解決方案,你解決了一個通用性的問題,然后嵌套使用,就能夠解決更多的問題,只需要付出少量的思維成本。

協議是問題解決方案的描述,或者說要解決這個問題大家都應該遵守的規則。就像網絡的tcp協議,你要基于tcp通信你就需要遵循這個協議。

實現是針對于某類環境的實施方案,比如linux上對于TCP的實現還有windows上對于TCP的實現。雖然都是一個協議,但是大家的實現方式不一樣,有基于c寫的,有基于c++寫的.

而應用是真對具體的問題域提出的實施方案,比如我們做了一個喲呵校園的聊天軟件使用了tcp進行socket通信。

解決方案設計

??榧渫ㄐ判閁RL

那我們首先要做的就是針對??榧渫ㄐ盼侍夤顧家桓魴?。一個為了解決??榧渫ㄐ盼侍獯蠹葉甲袷氐墓嬖?。其實關于這個問題在今年下半年,業界飄來一股router風。大家都在??榛蟮耐ㄐ盼侍饃獻鞒雋瞬煌某⑹?。而且甚至為此進行了一場博客間的辯論。仔細分析一下,就能發現大家雖各有意見,但是基本上都同意使用URL的方案來解決這個問題。所爭執的不同在于實現方案上的差異。而此處的URL正是我們所謂的協議部分。

統一資源定位符(或稱統一資源定位器/定位地址、URL地址等[1],英語:Uniform / Universal Resource Locator,常縮寫為URL),有時也被俗稱為網頁地址(網址)。如同在網絡上的門牌,是因特網上標準的資源的地址(Address)。它最初是由蒂姆·伯納斯-李發明用來作為萬維網的地址。現在它已經被萬維網聯盟編制為因特網標準RFC 1738。

為何如此?

回到最開始我們描述的問題中第一點: ??櫸⑾?。其實也就是??檎庵腫試吹畝ㄎ晃侍?,這個和URL設計的初衷是不謀而合的。URL整套的設計思路就是在整體的互聯網中解決信息孤島,讓各個信息孤島之間能夠進行資源發現和資源調用而設計。而我們目前所要處理的??榧渫ㄐ盼侍?,其實是這個宏大問題域的一個子集。因而選用URL協議,是一個非常順理成章的事情。另外一點,這里真心沒必要重新造一個類似于URL的協議的輪子出來的。URL協議中能夠非常完美的解決這個問題。

在iOS中基于URL協議的??榧渫ㄐ攀迪諨ZURLRoute

其實業界這個route的實現已經有千千萬萬了,為啥我還要再寫一個?一個是因為原有的一些庫的模型和我所想象的不吻合,一個是因為我實現不想削足適履去適配他們的模型。所以本著造輪子的作孽心態還是自己寫。其實也不是非常復雜。

URL協議解決了??櫸⑾值奈侍?,但是是個靜態的txt,并不具備exe的能力。我們可以通過定義一個類似于:

yoho://innerfuction/viewcontroller/showuserinfo?uid=22&xx=33

來讓一個??槎醞廡浦С窒允居沒晗感畔⒌姆?。但是我們要如何使用這個服務呢?很多Route的實現是通過URL直接將對應的ViewController返回,然后由調用方再去調用接口配置ViewController,而后調用方進行push或者present。而我認為這種方式不是很合理,做為調用發應該盡可能少的知道服務提供方的信息。服務怎么被彈起,應該是由服務方自己決定的,而不是調用方。最好只知道一個URL還有支持什么樣的服務就好了,最好能把交互接口精簡、精簡、再精簡。

而思考了一下很多route庫之所以沒能夠做到??櫓歡醞獗┞︰RL就可以的一個很重要的原因,就是在ViewController被彈出的時候,iOS需要一個調起的ViewController

UIViewController* aVC = [UIViewController new];
//配置aVC需要參數
....
[self.navigationController pushViewController:aVC animated:YES];

就是必須知道當前界面是在哪里,你才能去push下一個界面。只有知道這個self.navigationController上下文信息才行。所以很多事情只能在調用方來處理。我覺得這種方式制約著被調用方需要拿到服務提供方的一個實例才行。每一個問題背后都有一個解決方案。于是我在自己造的輪子中使用了全局UI堆棧的方式解決了這個問題。

通過構造了被調用的上下文信息類DZURLRequestContext,用于攜帶調用方的上下文信息來解決這個問題。上下文信息中攜帶了當前UI的堆棧信息,能夠方便定位用哪個VC做為起點,來彈出下一個頁面。當然使用這個context還有另外一個原因就是因為URL中能夠傳輸的參數類型是受限的,只能傳輸NSString類型,對于一個實例則不能傳輸。為了傳輸實例參數也需要這樣的一個context環境。

這樣在調用一個頁面的服務的時候,就能夠做到如下所示極致簡單:

[[DZURLRoute defaultRoute] routeURL:DZURLRouteQueryLink(kYHURLSacnQRCode, @{})];

當然該庫首先是解決了通過URL調用的問題,而后才是上面說的這些優化問題。同時,也針對很多不同的應用場景提供了解決方案。

而具體的應用問題,就是APP內部自己的事情了,不展開敘述?;舊隙際塹饔每飩涌詰氖慮?,沒有太多的表述價值。

來源:cocoachina

上一篇: IOS把圖片緩存到本地的幾種方法

下一篇: 新的iOS 10.3公測版來了:還有macOS更新

分享到: 更多
赌钱押大小的网站 快三怎么玩法介绍视频 彩世家能预测的软件 mg电子网址 快三大小单双稳赚投注 mg助手 重庆时时全天候计划 香港时时彩开奖查询 北京pk10计划手机app 时时彩平台哪个好 11选5计划软件哪个好用吗 刘伯温6374cm资料网站 w 麻将游戏单机 体育直播 四川时时走势图开奖号码 彩票跟计划亏了