設(shè)計(jì)模式

常用的面向?qū)ο笤O(shè)計(jì)方法和設(shè)計(jì)模式

MVC坤溃?

Model:表示業(yè)務(wù)數(shù)據(jù)對(duì)象拍霜;View:展現(xiàn)數(shù)據(jù)的 UI;Controller:Model 跟 View 之間的粘合劑薪介。一方面對(duì) View 上的行為作出反應(yīng)祠饺,通常會(huì)涉及到 Model 的更改;

另一方面將 Model 的改動(dòng)反映到 View 上汁政。由于 Controller 作為粘合劑的存在道偷,View 和 Model 只需要跟 Controller 交互,而不知道另一方的存在记劈。

這樣勺鸦,View 和 Model 作為獨(dú)立可復(fù)用的組件,Controller 里處理業(yè)務(wù)邏輯目木。聽起來這樣的架構(gòu)很清晰直觀换途,實(shí)際應(yīng)用中,MVC 對(duì)于不是很復(fù)雜的 App 也是非常高效的刽射。

但對(duì)稍復(fù)雜些的 App军拟,MVC 使用起來就會(huì)非常吃力。你可能聽過 MVC 也被簡(jiǎn)稱為 Massive View Controller誓禁,這就是原因所在 懈息。

View Controller 承擔(dān)的職責(zé)太多:網(wǎng)絡(luò)請(qǐng)求漓拾、數(shù)據(jù)訪問和存儲(chǔ)戒祠、UI 的調(diào)整和組合姜盈、業(yè)務(wù)邏輯馏颂、View 的 delegate救拉、data source亿絮、狀態(tài)的維護(hù)與單一責(zé)任準(zhǔn)則(Single Responsibility Principle)背道而馳派昧。

過于臃腫的 View Controller 使 App 的維護(hù)成本非常高蒂萎。盡管把網(wǎng)絡(luò)請(qǐng)求以及數(shù)據(jù)訪問和存儲(chǔ)放到了 Model 里,但由于對(duì)象邊界的定義不夠清晰纳寂,大部分 View Controller 依然很臃腫烈疚,上千行的 View Controller 很常見爷肝。

關(guān)于 View Controller 有個(gè)準(zhǔn)則:如果一個(gè) View Controller 超過了 300 行代碼灯抛,那它一定做了責(zé)任范圍以外的事对嚼。

更不幸的是由于一些職責(zé)移交給 Model纵竖,導(dǎo)致 Model 也變得臃腫起來靡砌。原來唯一可以做 Unit Test 的 Model 現(xiàn)在測(cè)試也很困難通殃。

為解決 Massive View Controller 的問題画舌,MVVM曲聂、VIPER 等架構(gòu)應(yīng)運(yùn)而生朋腋。要發(fā)揮 MVVM 的優(yōu)勢(shì)乍丈,需要有 Reactive。Reactive 增加學(xué)習(xí)成本的同時(shí)忆矛,也讓調(diào)試變得更困難催训。

VIPER雖然能平衡責(zé)任的分配漫拭,但由于引入過多對(duì)象采驻,維護(hù)成本高礼旅。一個(gè)簡(jiǎn)單的頁面也要求新增多個(gè)類和大量傻瓜代碼痘系。

MVVM 汰翠?

MVVM 架構(gòu)是 MV(X) 里面最新的一個(gè)复唤,它的出現(xiàn)已經(jīng)考慮到了 MV(X) 模式之前所遇到的問題苟穆。

理論上來說雳旅,Model - View - ViewModel 看起來非常棒攒盈。View 和 Model 已經(jīng)很熟悉了型豁,中間人的角色VC控制器也很熟悉了迎变,但是在MVVM架構(gòu)里中間人的角色由VC控制器變成了ViewModel衣形。

iOS 里面的 ViewModel 到底是個(gè)什么東西呢谆吴?ViewModel能持有Model進(jìn)而修改Model句狼,同時(shí)能夠隨時(shí)監(jiān)聽Model的屬性數(shù)據(jù)變化進(jìn)而來開啟事件芜繁,因?yàn)閂iewModel同時(shí)持有View骏令,所以能夠在監(jiān)聽Model變化開啟的事件里直接對(duì)View進(jìn)行更新榔袋。

綁定View和ViewModel的方法包括:

1凰兑、使用基于 KVO 的綁定庫(kù)吏够,比如 RZDataBinding 或者 SwiftBond播急。
2桩警、使用全量級(jí)的函數(shù)式響應(yīng)編程框架,比如ReactiveCocoa捶枢、RxSwift 或者 PromiseKit烂叔。

實(shí)際上长已,現(xiàn)在提到「MVVM」你應(yīng)該就會(huì)想到 ReactiveCocoa术瓮,反過來也是一樣胞四。

雖然我們可以通過簡(jiǎn)單的綁定來實(shí)現(xiàn) MVVM 模式辜伟,但是 ReactiveCocoa(或者同類型的框架)會(huì)讓你更大限度的去理解 MVVM导狡。

當(dāng)然響應(yīng)式編程框架(FRF)也有一點(diǎn)不好的地方負(fù)責(zé)的地方就是學(xué)習(xí)曲線陡峭旱捧,如果半懂不懂很容易讓事情更糟枚赡。什么地方出錯(cuò)需要花費(fèi)更多的時(shí)間去調(diào)試贫橙。

MVP卢肃?

MVP(被動(dòng)變化的 View)莫湘,在 MVC 里面 View 和 Controller 是耦合緊密的逊脯,但對(duì) MVP 里面的 Presenter 來講军洼,它根本不關(guān)注 ViewController 的生命周期匕争,而且 View 也能被簡(jiǎn)單 mock 出來甘桑,所以在 Presenter 里面基本沒什么布局相關(guān)的代碼跑杭,它的職責(zé)只是通過數(shù)據(jù)和狀態(tài)更新 View德谅。

在 MVP 架構(gòu)里面窄做,UIViewController 的那些子類其實(shí)是屬于 View 的椭盏,而不是 Presenter掏颊。

這種區(qū)別提供了極好的可測(cè)性蚯舱,但是這是用開發(fā)速度的代價(jià)換來的枉昏,因?yàn)槟惚仨氁謩?dòng)的去創(chuàng)建數(shù)據(jù)和綁定事件兄裂。

MVP 架構(gòu)擁有三個(gè)真正獨(dú)立的分層晰奖,所以在組裝的時(shí)候會(huì)有一些問題匾南,而 MVP 也成了第一個(gè)披露了這種問題的架構(gòu)蛆楞。

因?yàn)槲覀儾幌胱?View 知道 Model 的信息豹爹,所以在當(dāng)前的 ViewController(角色其實(shí)是 View)里面去進(jìn)行組裝肯定是不正確的臂聋,我們應(yīng)該在另外的地方完成組裝孩等。

比如,我們可以創(chuàng)建一個(gè)應(yīng)用層(app-wide)的 Router 服務(wù)冰垄,讓它來負(fù)責(zé)組裝和 View-to-View 的轉(zhuǎn)場(chǎng)播演。

這個(gè)問題不僅在 MVP 中存在写烤,在接下來要介紹的模式里面也都有這個(gè)問題洲炊。

MVP把大部分的職責(zé)都分配到了 Presenter 和 Model 里面暂衡,而 View 基本上不需要做什么(在上面的例子里面狂巢,Model 也什么都沒做)唧领。

可測(cè)性 - 簡(jiǎn)直棒,我們可以通過 View 來測(cè)試大部分的業(yè)務(wù)邏輯胯杭。

易用 - 就我們上面那個(gè)簡(jiǎn)單的例子來講做个,代碼量差不多是 MVC 架構(gòu)的兩倍居暖,但是 MVP 的思路還是蠻清晰的膝但。

MVP 架構(gòu)在 iOS 中意味著極好的可測(cè)性和巨大的代碼量。

還存在著另一種的 MVP - Supervising Controller MVP莺奸。這個(gè)版本的 MVP 包括了 View 和 Model 的直接綁定温学,與此同時(shí) Presenter(Supervising Controller)仍然繼續(xù)處理 View 上的用戶操作甚疟,控制 View 的顯示變化轧拄。

MVVM比較MVP檩电?

  • 劃分性俐末。MVVM 框架里面的 View 比 MVP 里面負(fù)責(zé)的事情要更多一些卓箫。MVVM是通過 ViewModel 的數(shù)據(jù)綁定來更新View的數(shù)據(jù)烹卒,而MVP只是把所有的事件統(tǒng)統(tǒng)交給 Presenter 去進(jìn)行數(shù)據(jù)處理但并不負(fù)責(zé)更新View的數(shù)據(jù),這也是MVP無法很好使用FRP響應(yīng)式框架的原因馁筐。

  • 可測(cè)性敏沉。在MVVM中盟迟, ViewModel 對(duì)View 是一無所知的潦闲,而View則完全依賴ViewModel處理數(shù)據(jù)并釋放出處理結(jié)果的信號(hào)辖众。因此MVVM的測(cè)試ViewModel里面的邏輯漏洞變得特別簡(jiǎn)單凹炸。

  • 易用性啤它。在實(shí)際的應(yīng)用當(dāng)中 MVVM 會(huì)更簡(jiǎn)潔一些变骡。在 MVP 下你必須要把 View 的所有事件都交給 Presenter 去處理塌碌,而且需要手動(dòng)的去更新 View 的狀態(tài);而在 MVVM 下瓢捉,你只需要用使用KVO或是ReactiveCocoa綁定就可以解決泡态。而且MVVM 所有框架中唯一自動(dòng)更新視圖的框架桐汤,因?yàn)樵?View 上已經(jīng)做了數(shù)據(jù)綁定员萍,只要ViewModel持有的Model屬性的特定屬性值發(fā)送變化拣度,自動(dòng)就會(huì)發(fā)送數(shù)據(jù)數(shù)據(jù)變化的信號(hào)抗果,然后更新View上UI控件的值日麸。

VIPER 逮光?

VIPER框架不屬于任何一種 MV(X) 框架代箭。

MV(X) 本質(zhì)上是把模塊分成三層,X無論是什么睦霎,都是器管道紐帶連接的作用梢卸。

但是VIPER能夠具備更細(xì)的顆粒度走诞,將模塊分成了五層。

1、Interactor(交互器) 處理數(shù)據(jù)(Entities)或網(wǎng)絡(luò)請(qǐng)求的業(yè)務(wù)邏輯古毛。
2彰触、Presenter(展示器) 處理UI相關(guān)的業(yè)務(wù)邏輯,可以調(diào)用 Interactor 中的方法來屬性數(shù)據(jù)塞绿。3沟涨、Entities(實(shí)體)作為一純粹的數(shù)據(jù)對(duì)象只是用來規(guī)范數(shù)據(jù)和記錄數(shù)據(jù)。
4棋返、Router(路由)主要是聯(lián)系 VIPER各個(gè)模塊之間的紐帶射沟。

MV(X)對(duì)比VIPER ?

  • 劃分性。Controller/Presenter/ViewModel 的職責(zé)里面准潭,只有 UI 的展示功能被轉(zhuǎn)移到了 Presenter 里面泼掠。Presenter 不具備直接更改數(shù)據(jù)的能力腻豌。但是毫無疑問的惹骂,VIPER 在職責(zé)劃分方面是做的最好的著拭,畢竟顆粒度分了五層。

  • 可測(cè)性。理所當(dāng)然的,職責(zé)劃分的越好,測(cè)試起來就越容易柱搜。

  • 易用性健爬。良好的職責(zé)劃分就意味著一個(gè)小小的任務(wù)设拟,可能就需要你為各種類寫大量的接口,維護(hù)代價(jià)直線升高。

后臺(tái)架構(gòu)?

服務(wù)器端開發(fā)常用Service Oriented Architecture服務(wù)導(dǎo)向架構(gòu)休里,把業(yè)務(wù)分成了多個(gè)邏輯獨(dú)立的組件。

一個(gè)組件相當(dāng)于一個(gè) Service做粤,封裝了與其業(yè)務(wù)相關(guān)的功能堵泽,如 UserService 負(fù)責(zé)用戶的注冊(cè)尤辱、登入等,而 BabyService 有 Baby 的增加圃酵、移除罗捎、以及數(shù)據(jù)的記錄等。

Service 是對(duì)整個(gè)架構(gòu)縱向邏輯切分的結(jié)果根悼。

拋開業(yè)務(wù)邏輯談 Service 意義不大,Service 通常與數(shù)據(jù)庫(kù)表的設(shè)計(jì)緊密相關(guān)糊肤。

橫向的邏輯切分將 Baby App iOS 的架構(gòu)自上而下切分成三個(gè)層(Layer):應(yīng)用層(Application Layer)拗踢、服務(wù)層(Service Layer)、數(shù)據(jù)層(Data Access Layer)陡叠。

服務(wù)層和數(shù)據(jù)層把復(fù)雜的邏輯封裝起來拙徽,作為 Framework 提供接口給上層調(diào)用裁眯。

應(yīng)用層只能調(diào)用服務(wù)層暴露出來的接口它改,而不能直接調(diào)用數(shù)據(jù)層抹凳。

層次結(jié)構(gòu)加強(qiáng)了可重用性和可測(cè)試性嘁扼。應(yīng)用層調(diào)用服務(wù)層提供的簡(jiǎn)單接口獲得數(shù)據(jù)或者實(shí)行用戶操作访娶。

服務(wù)層也不需要知道數(shù)據(jù)層中網(wǎng)絡(luò)請(qǐng)求割笙,服務(wù)器同步走净,以及數(shù)據(jù)持久化的具體實(shí)現(xiàn)蜓堕。

服務(wù)層息尺,數(shù)據(jù)層搂誉,以及應(yīng)用層都能很容易實(shí)現(xiàn)各自的單元測(cè)試(Unit Test)侮腹。Framework 是很棒的工具至非。把服務(wù)層和數(shù)據(jù)層打包成 Framework,不僅幫助構(gòu)建解耦可重用的代碼涨颜,同時(shí) App 的結(jié)構(gòu)和業(yè)務(wù)邏輯也更加清晰。

應(yīng)用層(Application Layer)應(yīng)用層也可以叫展示層(Presentation Layer)酒来,負(fù)責(zé) UI 跟 展示邏輯卢未。

從Code角度說,就是 UIView 跟 UIViewController 的集合堰汉。

復(fù)雜的邏輯都封裝到了下層辽社,UIViewController 就變得十分輕量。

View Controller主要負(fù)責(zé)三件事:

1翘鸭、從 Service 獲得數(shù)據(jù)(ViewModel)并展示
2滴铅、響應(yīng)用戶操作,調(diào)用相應(yīng)的 Service 接口
3就乓、監(jiān)聽 Service 層發(fā)出的消息汉匙,并執(zhí)行相應(yīng)操作,如更新 UI生蚁。

從 Service 獲取的 ViewModel 實(shí)例并不是 NSManagedObject 或者其他持久化的 model 實(shí)例噩翠,跟 MVVM 中的 ViewModel 也不一樣。

它只是簡(jiǎn)單的 Swift Struct邦投,提供應(yīng)用層需要的數(shù)據(jù)值伤锚。

使用 Struct 結(jié)構(gòu)體的好處主要是:

1、值類型(Value Type): 簡(jiǎn)單志衣、容易理解屯援,線程安全
2猛们、松耦合,減少 View Controller 之間可能的交互
3狞洋、減少了 Statefulness 和 Mutability似的應(yīng)用運(yùn)行更高效弯淘、占用內(nèi)存更少。

使用 Struct 也就意味著想要底層持久化 Model 的更改反映到 UI 上徘铝,你必須通過 Service 再抓一次數(shù)據(jù)耳胎。

也許有人認(rèn)為這是使用 Struct 的一個(gè)缺點(diǎn),其實(shí)不是惕它,這應(yīng)該是優(yōu)點(diǎn)。因?yàn)?Immutable 的 ViewModel 废登,讓 View Controller 變得更加簡(jiǎn)單淹魄,你不用擔(dān)心其他地方的代碼會(huì)更改你的 ViewModel 實(shí)例。

調(diào)試起來也會(huì)更加方便堡距,代碼更容易理解甲锡、可讀更高。

WWDC 中有好幾個(gè)視頻都對(duì) Struct 的使用和優(yōu)勢(shì)進(jìn)行了詳解羽戒。服務(wù)層(Service Layer)服務(wù)層定義了一系列 Service 和供給應(yīng)用層使用的 ViewModel缤沦。

Service 封裝了 App 主要的業(yè)務(wù)邏輯,負(fù)責(zé)把底層持久化的 Model 和網(wǎng)絡(luò)請(qǐng)求返回的 JSON 轉(zhuǎn)換為 ViewModel易稠,再提供給應(yīng)用層使用缸废。

這樣的分離即加強(qiáng)了 Immutablility 和 Statelessness,也讓應(yīng)用層中的 ViewController 更輕量驶社,只需幾行 Service calls企量。

Service 雖然承擔(dān)大部分業(yè)務(wù)邏輯,但一個(gè) Service 通常也就 300 行左右的代碼量亡电,這得益于數(shù)據(jù)層的封裝和抽象届巩。

數(shù)據(jù)層(Data Access Layer)的作用是提供簡(jiǎn)化的數(shù)據(jù)訪問接口,主要有 3 個(gè)模塊:數(shù)據(jù)存儲(chǔ)(Persistence)份乒、網(wǎng)絡(luò)請(qǐng)求(Network)恕汇、數(shù)據(jù)同步(Data Synchronization)。

數(shù)據(jù)存儲(chǔ)我們使用的是 Core Data或辖,也可以用 Realm 或者其他數(shù)據(jù)庫(kù)代替瘾英。

網(wǎng)絡(luò)請(qǐng)求我們使用了 Moya 進(jìn)行抽象,使 API 的設(shè)計(jì)和調(diào)用更簡(jiǎn)潔孝凌,并支持我們 Server 自定義的錯(cuò)誤方咆。數(shù)據(jù)同步模塊,會(huì)自動(dòng)同步本地和服務(wù)器端的用戶數(shù)據(jù)蟀架。

MVC 因 Controller 的臃腫而遭到眾人詬病瓣赂。但其實(shí) MVC 作為最基礎(chǔ)的設(shè)計(jì)模式榆骚,展現(xiàn)了一個(gè)架構(gòu)的精髓 - 抽象分離。

從整體看煌集,數(shù)據(jù)層是 Model妓肢,業(yè)務(wù)層是 Controller,應(yīng)用層是 View苫纤。

如果看細(xì)節(jié)的地方碉钠,應(yīng)用層跟也務(wù)層提供的 ViewModel 也可以看做一個(gè) MVC:ViewModel - UIViewController - UIView.

單例?

單例作為Cocoa框架中被廣泛使用的核心設(shè)計(jì)模式之一卷拘。事實(shí)上喊废,蘋果開發(fā)者庫(kù)把單例作為 "Cocoa 核心競(jìng)爭(zhēng)力" 之一。應(yīng)用中我們經(jīng)常和單例打交道栗弟,比如 UIApplication 和 NSFileManager 等等污筷。我們?cè)陂_源項(xiàng)目、蘋果示例代碼和 StackOverflow 中見過了無數(shù)使用單例的例子乍赫。但這也不可避免地產(chǎn)生了不好的影響:

1瓣蛀、全局狀態(tài)

使用全局可變的狀態(tài)使得程序變得難以理解,難以調(diào)試雷厂。因?yàn)樵诿嫦驅(qū)ο缶幊痰囊淮蠡驹瓌t就是惋增,對(duì)于可變的變量狀態(tài)而言,作用域越小越能避免一個(gè)員工兩個(gè)老板的誤會(huì)改鲫。

2诈皿、隱式耦合

程序的任意模塊都可以訪問單例意味著任何和這個(gè)單例交互產(chǎn)生的副作用都會(huì)影響程序其他地方的任意代碼。這就表示即使是兩個(gè)完全獨(dú)立的模塊钩杰。也會(huì)因?yàn)閱卫峁┑墓蚕頎顟B(tài)而產(chǎn)生副作用影響纫塌。由于單例具有全局和多狀態(tài)的特性,導(dǎo)致隱式地在兩個(gè)看起來完全不相關(guān)的模塊之間建立了耦合讲弄。

3措左、單元測(cè)試

一個(gè)全局屬性變量的值長(zhǎng)期存在不消失(持久化狀態(tài))會(huì)嚴(yán)重干擾單元測(cè)試。比如說避除,A和B是兩個(gè)不同的模塊怎披,但是都共同持有了一個(gè)單例對(duì)象的屬性值,這時(shí)候就不滿足單元測(cè)試的前提條件瓶摆,兩個(gè)模塊相互獨(dú)立凉逛。

4、生命周期

在程序中添加一個(gè)單例時(shí)群井, “永遠(yuǎn)只會(huì)有一個(gè)實(shí)例”的原則可能會(huì)被打破状飞。例如賬號(hào)注銷用戶切換,舊用戶的存儲(chǔ)在全局單例之中的所有狀態(tài)數(shù)據(jù)都必須清理掉。同時(shí)也希望登錄的新用戶能夠使用一個(gè)全新的全局單例诬辈,而不是簡(jiǎn)單的刪除單例的數(shù)據(jù)值酵使。那么就必須在用戶注銷的時(shí)候置空舊用戶的單例類對(duì)象,新用戶登錄的時(shí)候?qū)嵗粋€(gè)新的單例類對(duì)象焙糟。但是假如說現(xiàn)在用戶單例類正在存儲(chǔ)異步下載的圖片口渔,如果突然置空舊用戶的單例類對(duì)象會(huì)造成繼續(xù)下載的圖片保留到了新用戶的單例里。所以必須保證在置空舊用戶的單例類對(duì)象之前將異步下載圖片的操作給關(guān)閉掉穿撮。但是問題就在于置空舊用戶的單例類對(duì)象時(shí)你很難準(zhǔn)確地判斷出單例實(shí)例的所有者(因?yàn)閱卫约汗芾碜约旱纳芷?缺脉,準(zhǔn)確判斷出“關(guān)閉”的單例是一個(gè)舊用戶的單例將變得非常的困難。

雜談悦穿?

雀圣和菜鳥正在觀看同一個(gè)人打麻將攻礼,雀圣能夠察覺到的內(nèi)容會(huì)遠(yuǎn)遠(yuǎn)超過新手,并非雀圣火眼金睛咧党,而是掌握了無形的武器秘蛔,通過建立一整套思維抽象,雀圣能夠透過現(xiàn)象看到本質(zhì)傍衡,把對(duì)原始現(xiàn)象的感知轉(zhuǎn)換成對(duì)目前局勢(shì)簡(jiǎn)明扼要的理解。雀圣在看到牌局的一瞬間负蠕,就會(huì)聯(lián)想到某種進(jìn)攻戰(zhàn)術(shù)的成功蛙埂。這就叫觀察能力。

最好學(xué)些架構(gòu)的方式就是先經(jīng)過照貓畫虎式的時(shí)實(shí)踐遮糖,然后系統(tǒng)地培訓(xùn)設(shè)計(jì)方法绣的。

同一個(gè)應(yīng)用里面,即便有幾種混合的架構(gòu)模式也是很正常的一件事情欲账。比如:開始的時(shí)候屡江,你用的是 MVC 架構(gòu),后來你意識(shí)到有一個(gè)特殊的頁面用 MVC 做的的話維護(hù)起來會(huì)相當(dāng)?shù)穆闊┤唬贿@個(gè)時(shí)候你可以只針對(duì)這一個(gè)頁面用 MVVM 模式去開發(fā)惩嘉,對(duì)于之前那些用 MVC 就能正常工作的頁面,你完全沒有必要去重構(gòu)它們踢故,因?yàn)閮煞N架構(gòu)是完全可以和睦共存的

MVVM 配合綁定機(jī)制效果最好文黎,這個(gè)綁定機(jī)制就是RAC,使用MVC只能感受到RAC的部分好處殿较。一說到綁定耸峭,自然就是想到了 KVO(Key-Value Observation)。然而淋纲,對(duì)于一個(gè)簡(jiǎn)單的綁定都需要很大的樣板代碼劳闹,更不用說有許多屬性需要綁定了。所以ReactiveCocoa橫空出世,雖然MVVM 并未強(qiáng)制我們使用 ReactiveCocoa本涕。但是MVVM 在良好的綁定框架下更能釋放出潛力业汰。

模塊如何劃分?

桌面負(fù)責(zé)模擬控制臺(tái)和狀態(tài)顯示偏友、嵌入式負(fù)責(zé)設(shè)備控制和狀態(tài)數(shù)據(jù)讀取開發(fā)技術(shù)如何選型
如何適應(yīng)可能發(fā)生的變化蔬胯、交互機(jī)制

如何設(shè)計(jì)程序?

看別人的設(shè)計(jì)成果位他,體會(huì)別人的設(shè)計(jì)過程氛濒,試著自己來設(shè)計(jì)。討論功能需求鹅髓、討論非功能需求中的質(zhì)量屬性需求舞竿、解決待完成任務(wù)的限制條件的約束需求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窿冯,一起剝皮案震驚了整個(gè)濱河市骗奖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌醒串,老刑警劉巖执桌,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芜赌,居然都是意外死亡仰挣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門缠沈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膘壶,“玉大人,你說我怎么就攤上這事洲愤⊥前牛” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵柬赐,是天一觀的道長(zhǎng)亡问。 經(jīng)常有香客問我,道長(zhǎng)躺率,這世上最難降的妖魔是什么玛界? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮悼吱,結(jié)果婚禮上慎框,老公的妹妹穿的比我還像新娘。我一直安慰自己后添,他們只是感情好笨枯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般馅精。 火紅的嫁衣襯著肌膚如雪严嗜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天洲敢,我揣著相機(jī)與錄音漫玄,去河邊找鬼。 笑死压彭,一個(gè)胖子當(dāng)著我的面吹牛睦优,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壮不,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼汗盘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了询一?” 一聲冷哼從身側(cè)響起隐孽,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎健蕊,沒想到半個(gè)月后菱阵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缩功,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年送粱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掂之。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脆丁,靈堂內(nèi)的尸體忽然破棺而出世舰,到底是詐尸還是另有隱情,我是刑警寧澤槽卫,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布跟压,位于F島的核電站,受9級(jí)特大地震影響歼培,放射性物質(zhì)發(fā)生泄漏震蒋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一躲庄、第九天 我趴在偏房一處隱蔽的房頂上張望查剖。 院中可真熱鬧,春花似錦噪窘、人聲如沸笋庄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽直砂。三九已至菌仁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間静暂,已是汗流浹背济丘。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洽蛀,地道東北人摹迷。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像辱士,于是被迫代替她去往敵國(guó)和親泪掀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 傳統(tǒng)模式下的開發(fā)MVCMVVM基于面向協(xié)議MVP的介紹MVP實(shí)戰(zhàn)開發(fā)說在前面:相信就算你是個(gè)iOS新手也應(yīng)該聽說過...
    行走的菜譜閱讀 3,144評(píng)論 1 5
  • 一颂碘、概述 通過上一篇文章的學(xué)習(xí)异赫,我們對(duì)關(guān)于MVC的弊端的產(chǎn)生和MVVM中viewModel的職責(zé)及其使用注意事項(xiàng),...
    CoderMikeHe閱讀 28,355評(píng)論 110 353
  • 平樂和南憶走在白霆身后头岔,仿佛已經(jīng)看到了這個(gè)故事的結(jié)局塔拳。 “白霆,對(duì)不起峡竣,最終還是連累你了靠抑。”小乞忍著身上的痛有氣無...
    小哈兒閱讀 189評(píng)論 2 1
  • 南方的八月仍是盛夏适掰,華氏九十多度颂碧,占地七百多畝的體育場(chǎng)路面人影稀寥,間或閃過也是打著低低的遮陽傘类浪。 此刻正值晌午载城,...
    珂鳴閱讀 416評(píng)論 0 0
  • 大米,是我的好朋友费就,不是因?yàn)樗L(zhǎng)的像大米诉瓦,而是因?yàn)樗珢鄢源竺琢恕?剛認(rèn)識(shí)他的時(shí)候,我一度認(rèn)為眼前這個(gè)瘦瘦高高的男...
    花枝招展的貓閱讀 132評(píng)論 0 0