Swift-面向協(xié)議編程(轉(zhuǎn)載)



Swift的核心

我們可以通過等式的傳遞性來理解swift:

Swift的核心是面向協(xié)議的編程调违。

面向協(xié)議的編程的核心是抽象(abstraction)和簡(jiǎn)化(simplicity)。

所以swift的核心就是抽象和簡(jiǎn)化泻轰。

可能對(duì)我的標(biāo)題感到詫異技肩。我并不是說子類沒有價(jià)值,尤其在使用單一繼承(single

inheritance)的情況下浮声,類和子類當(dāng)然是強(qiáng)有力的工具亩鬼。然而我想說的是,iOS日常開發(fā)的問題是對(duì)類和繼承的過度使用阿蝶。作為面向?qū)ο蟮木幊陶?/p>

(object-oriented programmer雳锋,后面統(tǒng)一替換為OOP編程者;object-oriented

programming后面統(tǒng)一簡(jiǎn)寫為OOP)我們總是會(huì)自然的傾向于使用引用類型和類去解決問題羡洁,但是我個(gè)人還是認(rèn)為應(yīng)該反過來玷过,傾向于用值類型代替引

用類型。我們還是要去寫模塊化的,可伸縮的并且可重用的代碼辛蚊,這一點(diǎn)不會(huì)變粤蝎。swift中強(qiáng)大的值類型就可以幫我們實(shí)現(xiàn)此目的,且不需要對(duì)引用類型有過強(qiáng)

的依賴袋马。我認(rèn)為不僅面向協(xié)議的編程(protocol oriented

programming初澎,后統(tǒng)一替換為POP)可以幫我們實(shí)現(xiàn)這點(diǎn),另外2種編程類型也可以虑凛,且都具有抽象和簡(jiǎn)化的核心思想碑宴,這兩種分別是:面向值的編程

(value-oriented programming,后面統(tǒng)一替換成VOP)和函數(shù)式編程(functional programming)桑谍。

說清楚延柠,我絕不是這些種編程類型(POP,VOP和函數(shù)式編程)的專家锣披。和你一樣贞间,從MMM時(shí)代(manual memory management -

手動(dòng)內(nèi)存管理)開始我就是一個(gè)OOP編程者。通過自學(xué)雹仿,從開始我就很重視值抽象(value

abstraction)和簡(jiǎn)化的思想增热。我都沒有意識(shí)到自己是一個(gè)傾向于函數(shù)式編程(functional

programming)的OOP編程者,而且很多時(shí)候用的都是VOP和POP的思路胧辽。這可能是我為什么在第一天就興高采烈的加入了swift的浪潮之中

的原因钓葫。在WWDC的一整周里,swift的核心理念與我認(rèn)為的該怎樣去編程是如此之契合票顾,這個(gè)感受一直充斥在我腦海中础浮。通過這篇文章,我希望能幫助你

(OOP的編程者)打開思路奠骄,去考慮該如何用更加Non-OOP(非OOP)的方式去解決問題豆同。

OOP的問題(和我不得不去學(xué)它的原因)

我會(huì)是第一個(gè)跳出來說的:不用OOP的話做出iOS應(yīng)用很難。Cocoa的核心就是OOP含鳞。沒有OOP的話你根本寫不出來一個(gè)iOS應(yīng)用影锈。有時(shí)候我會(huì)幻想這不是真的。如果你有不同觀點(diǎn)蝉绷,趕快證明我是錯(cuò)的吧鸭廷。我真的需要這樣,求你了熔吗,證明我是錯(cuò)的吧辆床!

不管怎么樣,你總會(huì)遇到必須用對(duì)象桅狠、用引用類型解決問題的時(shí)候讼载,然后由于Cocoa的規(guī)定而被迫使用類(classes)轿秧。這種情況下你碰到的問題都是我們大家熟知并熱愛的:

傳遞class的實(shí)例這個(gè)做法好像總是有種不可思議的能力:你想用一個(gè)實(shí)例的時(shí)候,讓這個(gè)實(shí)例的狀態(tài)(state)和你所期望的不一樣咨堤。(這是由于可變狀態(tài)(mutable state)導(dǎo)致菇篡,你這個(gè)對(duì)象的另一個(gè)享有者在它覺得合理的時(shí)候能夠改變此對(duì)象的屬性。)

果不用多繼承的話一喘,從一個(gè)很棒的class派生出子類從而獲得它的擴(kuò)展功能妨礙了你使用另外一些很棒的class的更多更能驱还,而且還增加了復(fù)雜性。(舉例

來說凸克,試著去把2個(gè)UITextField的子類結(jié)合起來议蟆,生成一個(gè)擁有這2者特性的超級(jí)UITextField吧。)

面一條的另外一個(gè)問題是會(huì)引出意外行為(unexpected

behavior)触徐。如果你遇見了類似上面一條所描述的情況咪鲜,你就陷入到了一個(gè)依賴問題中:你連接了2個(gè)superclass各自的特性狐赡,對(duì)于其中一個(gè)

superclass的一處改動(dòng)可能會(huì)給另外一個(gè)superclass帶來不良影響撞鹉。這就是被周知的class之間緊耦合(tight

coupling)所帶來的問題。

單元測(cè)試中的mocking颖侄。有些classes在系統(tǒng)中的環(huán)境狀態(tài)下耦合過于緊密鸟雏,

想完全測(cè)試這些classes就需要你創(chuàng)建每個(gè)class的假表象。我都不用告訴你本質(zhì)上你并沒有真正的測(cè)試了這個(gè)class览祖,你不過是在假裝測(cè)試它孝鹊。這

里就不提很多Mocking的庫(kù)是用運(yùn)行時(shí)的小把戲來造一個(gè)假的class了。

并發(fā)(Concurrency)問題展蒂。這和上面提到的可變狀態(tài)是伴隨出現(xiàn)的又活。你從多個(gè)線程中同時(shí)改變一個(gè)引用就會(huì)引起這個(gè)問題,在運(yùn)行時(shí)使對(duì)象之間的同步發(fā)生異常锰悼,這點(diǎn)也真的不用和你說了柳骄。

容易導(dǎo)致出現(xiàn)像上帝類(God classes -

承擔(dān)著很多subclasses需要的重要高層級(jí)代碼的所有責(zé)任),Blobs(有過多職權(quán)的classes)箕般,Lava

Flow(因?yàn)楹刑嗟姆欠ùa導(dǎo)致任何人都不敢碰的classes)等等這些種反面模式(anti patterns)耐薯。

POP 面向協(xié)議的編程

入OOP的反面模式特別容易。多半時(shí)間我們(包括我)就是太懶而不愿意去點(diǎn)File>New

File丝里。結(jié)果是在現(xiàn)有class的基礎(chǔ)上添加一個(gè)函數(shù)是如此輕松曲初,我們就不愿意從零開始建一個(gè)新的class了。如果你一直這么干杯聚,而且一直非常懶的從

一個(gè)"很重要"的class派生subclass的話臼婆,你就把上帝類/死星類給弄出來了。實(shí)際上我之前就這么干過:我給一個(gè)app里的每個(gè)view

Controller都加了能呈現(xiàn)一個(gè)指向navigationController的navigationBar的error

view的功能幌绍。唉目锭,我可真蠢评汰。直到要改動(dòng)那個(gè)Error上帝類行為的時(shí)候,我不得不把整個(gè)app都改一遍痢虹。這不是聰明的做法被去,你真應(yīng)該看看那些bug。

一個(gè)掌管一切的class = bug滿天飛

如果使用了POP奖唯,這個(gè)Error上帝類很大程度上就能很容易的抽象出來惨缆,以后改進(jìn)它也方便。(順便說下如果你想學(xué)POP丰捷,我極力推薦你去看這個(gè)視頻)坯墨。想想就會(huì)覺得好笑,因?yàn)樵谶@個(gè)視頻中Apple自己都說:

"從一個(gè)protocol開始病往,別從class開始捣染。"——Dave Abrahams: 毀你三觀教授

這是一個(gè)能展示(之前的方式)有多殘暴的例子:

1

2

3

4

5

6

7

8class?PresentErrorViewController:?UIViewController?{

varerrorViewIsShowing:?Bool?=false

func?presentError(message:?String?=?“Error!",?withArrow?shouldShowArrow:?Bool?=false,?backgroundColor:?UIColor?=?ColorSalmon,?withSize?size:?CGSize?=?CGSizeZero,?canDismissByTappingAnywhere?canDismiss:?Bool?=true)?{

//寫下了復(fù)雜的,脆弱的代碼

}

}

//說一下停巷,有100個(gè)class繼承了這個(gè)class

EveryViewControllerInApp:?PresentErrorViewController?{}

著項(xiàng)目的進(jìn)行事情馬上變的明了:并不是每一個(gè)UIViewController需要這個(gè)error邏輯耍攘,或是真的需要這個(gè)class所提供的每一個(gè)功能。

我團(tuán)隊(duì)里任何一個(gè)人都可以輕易的在這個(gè)superclass里改點(diǎn)兒什么畔勤,從而影響整個(gè)app蕾各。這就讓代碼變得脆弱。還使得代碼呈現(xiàn)出了多態(tài)庆揪。當(dāng)本應(yīng)該是

由子類決定它自己的行為式曲,這里的superclass卻給幫著決定了。下面是在swift 2.0中我們?nèi)绾斡肞OP來更好的構(gòu)建這段代碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15protocol?ErrorPopoverRenderer?{

func?presentError(message:?String,?withArrow?shouldShowArrow:?Bool,?backgroundColor:?UIColor,?withSize?size:?CGSize,?canDismissByTappingAnywhere?canDismiss:?Bool)

}

extension?UIViewController:?ErrorPopoverRenderer?{//使所有遵從于ErrorPopoverRenderer協(xié)議的UIViewController具有一個(gè)presentError的默認(rèn)實(shí)現(xiàn)

func?presentError(message:?String,?withArrow?shouldShowArrow:?Bool,?backgroundColor:?UIColor,?withSize?size:?CGSize,?canDismissByTappingAnywhere?canDismiss:?Bool)?{

//加上呈現(xiàn)error視圖的默認(rèn)實(shí)現(xiàn)

}

}

class?KrakenViewController:?UIViewController,?ErrorPopoverRenderer?{//Drop?the?God?class?and?make?KrakenViewController?conform?to?the?new?ErrorPopoverRenderer?Protocol.

func?methodThatHasAnError()?{

//…

//拋出error缸榛,原因是Kraken海妖今天吃人會(huì)感到不適吝羞。

presentError(/*blah?blah?blah?好多參數(shù)*/)

}

}

看,

這里發(fā)生了很炫酷的事情内颗。我們不僅消除了上帝類的存在钧排,還讓代碼更加的模塊化并增強(qiáng)了它的擴(kuò)展性。通過創(chuàng)建一個(gè)

ErrorPopoverRenderer協(xié)議起暮,就會(huì)讓任何遵循了該協(xié)議的class具有呈現(xiàn)出一個(gè)ErrorView的能力卖氨。還不止這些,我們的

KrakenViewController

class不用必須實(shí)現(xiàn)presentError這個(gè)函數(shù)负懦,因?yàn)槲覀償U(kuò)展了UIViewController筒捺,讓它提供了一個(gè)默認(rèn)實(shí)現(xiàn)。

唉不過等下纸厉!這有個(gè)問題系吭!我們每次想要呈現(xiàn)一個(gè)ErrorView的時(shí)候都必須要去實(shí)現(xiàn)每一個(gè)參數(shù)。這就有點(diǎn)兒讓人不爽了颗品,因?yàn)槲覀儾荒茉趐rotocol協(xié)議函數(shù)聲明中為參數(shù)提供默認(rèn)值肯尺。

我還挺喜歡這些參數(shù)的沃缘!更糟的是在讓代碼更具模塊化特征的過程中我們引入了復(fù)雜度。還是繼續(xù)吧则吟,用swift 2.0中新加的一個(gè)小妙招來多少的補(bǔ)償一下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15protocol?ErrorPopoverRenderer?{

func?presentError()

}

extension?ErrorPopoverRenderer?where?Self:?UIViewController?{

func?presentError()?{

//在這里加默認(rèn)實(shí)現(xiàn)槐臀,并提供ErrorView的默認(rèn)參數(shù)。

}

}

class?KrakenViewController:?UIViewController,?ErrorPopoverRenderer?{

func?methodThatHasAnError()?{

//…

//拋出error氓仲,原因是Kraken海妖今天吃人會(huì)感到不適水慨。

presentError()//Woohoo!?沒有參數(shù)了!我們現(xiàn)在有默認(rèn)實(shí)現(xiàn)了敬扛!

}

}

了晰洒,現(xiàn)在看起來已經(jīng)很不錯(cuò)了。我們不僅消除了這些煩人的參數(shù)啥箭,還用swift

2.0的新特性在protocol的層級(jí)上用Self給了presentError一個(gè)默認(rèn)實(shí)現(xiàn)谍珊。用Self意味著當(dāng)且僅當(dāng)協(xié)議的遵循者是繼承自

UIViewController的情況下,這個(gè)擴(kuò)展才會(huì)有效急侥。這就讓我們能夠把ErrorPopoverRenderer真的當(dāng)做是一個(gè)

UIViewController砌滞,而甚至不需要對(duì)后者做擴(kuò)展!更棒的是缆巧,從現(xiàn)在開始布持,Swift的運(yùn)行時(shí)是以靜態(tài)調(diào)度而非動(dòng)態(tài)調(diào)度去調(diào)用

presentError()方法豌拙。大致的意思就是我們?cè)诤瘮?shù)調(diào)用點(diǎn)給presentError()方法增強(qiáng)了一點(diǎn)性能陕悬。

哎,不過還是有個(gè)問題按傅。到這里我們POP的旅途暫時(shí)告一段落捉超,但對(duì)它的完善依舊不會(huì)停止。我們的問題就是如果只想對(duì)一部分參數(shù)使用默認(rèn)值唯绍,對(duì)剩下的不用默認(rèn)值該怎么做拼岳?在這方面用POP的話基本幫不上什么忙,但是我們可以尋求另外一種方法】雒ⅲ現(xiàn)在惜纸,我們使用VOP吧。

VALUE-ORIENTED PROGRAMMING

看到了吧绝骚,POP和VOP總是伴隨出現(xiàn)耐版。在上面的WWDC視頻鏈接中,Crusty提出了一些大膽的論斷:我們用struct和enum類型就可以做到一切class能做到的事压汪。我很大程度上同意這點(diǎn)粪牲,但沒這么極端。依我看止剖,protocol本質(zhì)上是把VOP粘合在一起的膠水腺阳,這點(diǎn)我和Crusty持相同態(tài)度落君。實(shí)際上既然我們說到了Swift的核心理念以及VOP,我想給你們看看從Andy Matuschak的精彩訪談中關(guān)于Swift中的VOP

的話題里面摘出來的一張極好的圖:

能看出來Swift的標(biāo)準(zhǔn)庫(kù)中亭引,僅有的4個(gè)class绎速,和余下的95個(gè)struct和enum的實(shí)例共同構(gòu)建了Swift功能的核心。

Andy如此闡述道:用Swift編程的時(shí)候我們要去考慮用一層很薄的對(duì)象層焙蚓,和一層很厚的值類型層朝氓。Class是有它們的地方,但是我想盡最大程度的去認(rèn)為它們的位置只應(yīng)該處于對(duì)象層中的一個(gè)很高的級(jí)別上主届,在這里通過操縱值類型層中的邏輯來管理各種行為赵哲。

"把邏輯和行為分開"——Andy Matuschak

你所了解的一樣,值類型被賦給一個(gè)變量或者常量君丁,抑或是傳給函數(shù)做參數(shù)時(shí)是它的值被拷貝的枫夺。這就讓值類型在任何時(shí)候只有一個(gè)享有者,從而降低復(fù)雜度绘闷。和引

用類型相反橡庞,在賦值過程中引用類型會(huì)有很多享有者,其中一部分你甚至都沒意識(shí)到印蔗。在任何時(shí)間點(diǎn)使用引用的話會(huì)帶來一些副作用:引用的享有者會(huì)搗蛋扒最,在背后

偷偷改變這個(gè)引用。Class = 高復(fù)雜度华嘹,值 = 低復(fù)雜度吧趣。

通過利用值類型的簡(jiǎn)約特性,咱們實(shí)現(xiàn)一下之前提過的默認(rèn)參數(shù)的設(shè)計(jì)吧耙厚。我們用的是Brian Gesiakvalue options paradigm方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24struct?Color?{

let?red:?Double

let?green:?Double

let?blue:?Double

init(red:?Double?=?0.0,?green:?Double?=?0.0,?blue:?Double?=?0.0)?{

self.red?=?red

self.green?=?green

self.blue?=?blue

}

}

struct?ErrorOptions?{

let?message:?String

let?showArrow:?Bool

let?backgroundColor:?UIColor

let?size:?CGSize

let?canDismissByTap:?Bool

init(message:?String?="Error!",?shouldShowArrow:?Bool?=true,?backgroundColor:?Color?=?Color(),?size:?CGSize?=?CGSizeZero,?canDismissByTappingAnywhere?canDismiss:?Bool?=true)?{

self.message?=?message

self.showArrow?=?shouldShowArrow

self.backgroundColor?=?backgroundColor

self.size?=?size

self.canDismissByTap?=?canDismiss

}

}

使用上面的選項(xiàng)型struct(是值類型G看臁)就使我們的POP帶上了一些VOP的色彩,如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15protocol?ErrorPopoverRenderer?{

func?presentError(errorOptions:?ErrorOptions)

}

extension?ErrorPopoverRenderer?where?Self:?UIViewController?{

func?presentError(errorOptions?=?ErrorOptions())?{

//在這里加默認(rèn)實(shí)現(xiàn)薛躬,并提供ErrorView的默認(rèn)參數(shù)俯渤。

}

}

class?KrakenViewController:?UIViewController,?ErrorPopoverRenderer?{

func?failedToEatHuman()?{

//…

//拋出error,原因是Kraken海妖今天吃人會(huì)感到不適型宝。

presentError(ErrorOptions(message:"Oh?noes!?I?didn't?get?to?eat?the?Human!",?size:?CGSize(width:?1000.0,?height:?200.0)))//Woohoo!?沒有參數(shù)了八匠!我們現(xiàn)在有默認(rèn)實(shí)現(xiàn)了!

}

}

你所見趴酣,對(duì)于用view controller做error處理梨树,我們給與它了一種完全抽象的,可伸縮的和模塊化的方式价卤,還不用強(qiáng)迫所有的view

controller去繼承一個(gè)上帝類劝萤。當(dāng)你有一個(gè)具有不同功能的上帝類的時(shí)候,上面的例子尤其能幫到你慎璧。除此之外床嫌,用這種方式去實(shí)現(xiàn)類似上面error

功能的其他功能時(shí)跨释,你把實(shí)現(xiàn)該功能的代碼放哪兒都行,不必做太多的重構(gòu)或者改變代碼框架厌处。

函數(shù)式編程

們來解決這個(gè)鳖谈。我也剛開始接觸函數(shù)式編程,不過我知道一點(diǎn):這種范式(paradigm)要求一種鼓勵(lì)編程者去避免可變數(shù)據(jù)(mutable

data)和改變狀態(tài)(changing

state)的編程方式阔涉。和數(shù)學(xué)函數(shù)類似缆娃,函數(shù)式編程是由一些輸出結(jié)果僅取決于輸入?yún)?shù)的函數(shù)組成,而且函數(shù)的輸出結(jié)果不會(huì)被本體之外的相依性

(dependency)所影響瑰排。這就是眾所周知的"data in, data

out"贯要,意思是每次傳進(jìn)來一個(gè)值,這個(gè)值傳出去的時(shí)候和傳進(jìn)來時(shí)候總要是一樣的椭住。想想單元測(cè)試就明白了崇渗!

如果我們用函數(shù)式的思想去寫代碼,就可以把VOP與函數(shù)式編程結(jié)合京郑,利用其中的諸多優(yōu)點(diǎn)宅广,這些優(yōu)點(diǎn)包括但不僅限于:

完全線程安全的代碼(值類型變量在并發(fā)代碼中被分配時(shí)是被拷貝的,意思是另一個(gè)線程更改不了與它平行線程中的變量)些举。

更詳盡的單元測(cè)試

不再需要在單元測(cè)試中用mock(用了值類型的變量就不用再重建一個(gè)必須使用mock對(duì)象的環(huán)境跟狱,只為了去測(cè)試僅僅少部分的功能。本質(zhì)上通過初始化一個(gè)從任意依賴關(guān)系中抽象出來的特性户魏,你可以重建任何你想要的東西驶臊。)

代碼更簡(jiǎn)潔(說實(shí)話,能和瓷器一樣精致)绪抛。

讓你身邊的小伙伴驚呆

很炫酷

讓Kraken瘋狂的崇拜你

什么時(shí)候用子類

什么時(shí)候應(yīng)該用子類呢资铡?答案是當(dāng)你沒選擇的時(shí)候电禀。比如:

當(dāng)系統(tǒng)要求的時(shí)候幢码。許多Cocoa的API要求你使用class,你不應(yīng)該非要用值類型來跟系統(tǒng)對(duì)著干尖飞。UIViewController是要派生子類的症副,要不然你的app就啥都沒有了。別跟系統(tǒng)對(duì)著干政基!

當(dāng)

你需要有東西來幫你管理在其他class實(shí)例之間的值類型變量贞铣,而且還需要與這些值類型變量通信的時(shí)候。對(duì)于這種情況Andy

Matuschak給了一個(gè)很好的例子:用一個(gè)class把一個(gè)值類型的繪圖系統(tǒng)計(jì)算好的值取過來沮明,傳遞給一個(gè)Cocoa的class來把這個(gè)繪圖系統(tǒng)繪

制到屏幕上辕坝。

當(dāng)你需要或者想在許多享有者之間做隱式共享的時(shí)候。此種情況的例子是Core Data荐健。數(shù)據(jù)持久化變幻無常酱畅,用Core Data的時(shí)候琳袄,使用子類給諸多需要同步的享有者做同步就很有效。但是要小心并發(fā)問題纺酸!這是你處理此類問題的時(shí)候必須要做的取舍窖逗。

當(dāng)你不知道對(duì)于引用類型來說它的拷貝意味著什么的時(shí)候。你會(huì)拷貝一個(gè)單例么(singleton)餐蔬?不會(huì)碎紊。你會(huì)拷貝一個(gè)UIViewController么?不會(huì)樊诺。一個(gè)window仗考?絕對(duì)不會(huì)。(你其實(shí)可以词爬,這是你的特權(quán)痴鳄。)

當(dāng)一個(gè)實(shí)例的聲明周期與外部效應(yīng)(external effect)綁定的時(shí)候,或者就只是需要一個(gè)穩(wěn)定個(gè)體(stable identity)的時(shí)候缸夹。單例就是特別典型的例子痪寻。

結(jié)論

為OOP的編程者我們已經(jīng)習(xí)慣了用class來解決問題。長(zhǎng)期以來我們開發(fā)了很多模式來彌補(bǔ)引用類型所帶來的弊端虽惭。我的觀點(diǎn)是在編程中換一種思路可以有效

的減輕對(duì)這類折衷方案的使用橡类。如果我們真的重視可伸縮性和可重用性,就得接受模塊化的編程才是正道芽唇。使用值類型并結(jié)合Swift

2.0中新增并改進(jìn)了的protocol特性就會(huì)輕松的達(dá)到這個(gè)目的顾画。雖然之前OOP的思維方式會(huì)使我們比較難用VOP和POP的方式來思考,但是在

swift中寫的多了匆笤,VOP和POP的模式就會(huì)開始成為我們的第二天性研侣。我們的大腦可能得需要我們多寫一些代碼才能適應(yīng)這種思維方式,但我相信iOS社

區(qū)作為一個(gè)整體能接納這些做法炮捧,從而極大的降低我們?nèi)粘=鉀Q問題的難度庶诡。Swift的核心是一個(gè)極為強(qiáng)大的值類型系統(tǒng),坦白說咆课,我們應(yīng)該一開始就用VOP

的思想磨練自己來發(fā)揚(yáng)這個(gè)值系統(tǒng)的優(yōu)勢(shì)末誓。但愿這篇文章能多多少少的幫助到你,讓你每天寫出來更加詳盡的书蚪,天生安全的代碼喇澡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市殊校,隨后出現(xiàn)的幾起案子晴玖,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呕屎,死亡現(xiàn)場(chǎng)離奇詭異宪萄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)榨惰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門拜英,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琅催,你說我怎么就攤上這事居凶。” “怎么了藤抡?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵侠碧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我缠黍,道長(zhǎng)弄兜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任瓷式,我火速辦了婚禮替饿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贸典。我一直安慰自己视卢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布廊驼。 她就那樣靜靜地躺著据过,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妒挎。 梳的紋絲不亂的頭發(fā)上绳锅,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音酝掩,去河邊找鬼鳞芙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庸队,可吹牛的內(nèi)容都是我干的积蜻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼彻消,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了宙拉?” 一聲冷哼從身側(cè)響起宾尚,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤振定,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后院尔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體说榆,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年牛郑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怠肋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淹朋,死狀恐怖笙各,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情础芍,我是刑警寧澤杈抢,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站仑性,受9級(jí)特大地震影響惶楼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诊杆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一歼捐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晨汹,春花似錦窥岩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至慨灭,卻和暖如春朦乏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氧骤。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工呻疹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人筹陵。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓刽锤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親朦佩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子并思,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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