創(chuàng)建者模式-原型模式(The prototype pattern)

本文大部分內(nèi)容翻譯至《Pro Design Pattern In Swift》By Adam Freeman语淘,一些地方做了些許修改巷蚪,并將代碼升級(jí)到了Swift2.0,翻譯不當(dāng)之處望多包涵杭措。

原型模式(The prototype pattern)

原型模式多用于創(chuàng)建復(fù)雜的或者耗時(shí)的實(shí)例柄沮,因?yàn)檫@種情況下审孽,復(fù)制一個(gè)已經(jīng)存在的實(shí)例使程序運(yùn)行更高效午阵;或者創(chuàng)建值相等躺孝,只是命名不一樣的同類數(shù)據(jù)。


理解

原型模式利用一個(gè)已經(jīng)存在的對(duì)象底桂,而非一個(gè)類或者一個(gè)結(jié)構(gòu)體植袍,去創(chuàng)建一個(gè)新的對(duì)象。這通常叫做克隆籽懦,因?yàn)樾聞?chuàng)建的對(duì)象是原型對(duì)象的一個(gè)完全復(fù)制于个,甚至包括在被復(fù)制之前對(duì)原型對(duì)象的存儲(chǔ)屬性的一些操作。

原型模式有三部操作:

  • 第一暮顺,需要?jiǎng)?chuàng)建對(duì)象的組件請(qǐng)求復(fù)制原型對(duì)象
  • 第二厅篓,原型對(duì)象的復(fù)制
  • 第三秀存,將復(fù)制的對(duì)象交給請(qǐng)求組件

值類型拷貝

當(dāng)你將一個(gè)值類型賦值給變量時(shí),Swift自動(dòng)的實(shí)現(xiàn)了原型模式羽氮。值類型是用結(jié)構(gòu)體來(lái)定義的或链,而且Swift所有內(nèi)建的類型在幕后都是用結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的。這就意味著你能僅僅依靠賦值給變量來(lái)復(fù)制String,Boolean,collection,enumeration,tuple和numeric類型,Swift將會(huì)復(fù)制原型的值并且用它來(lái)創(chuàng)建一個(gè)克隆档押。下面例子來(lái)展示值類型是如何被克隆的澳盐。

struct Appointment{
    var name:String
    var day:String
    var place:String
    
    func printDetails(label:String){
        print("\(label) with \(name) on \(day) at \(place)")
    }
}

var beerMeeting = Appointment(name: "Bob", day: "Mon", place: "Joe's Bar")

var workMeeting = beerMeeting

對(duì)應(yīng)的圖例:

接著我們修改workMeeting的值:

workMeeting.name = "Alice"
workMeeting.day = "Fri"
workMeeting.place = "Conference Rm 2"

此時(shí)對(duì)應(yīng)的圖例:

如果我們輸出的話,將會(huì)得到不同的結(jié)果:

Social with Alice on Fri at Conference Rm 2
Work with Alice on Fri at Conference Rm 

引用類型拷貝

用類創(chuàng)建出的對(duì)象是引用類型汇荐,而且當(dāng)你將它們賦值給變量的時(shí)候Swift并不會(huì)去復(fù)制它們洞就。相反,關(guān)于這個(gè)對(duì)象的一個(gè)新的引用被創(chuàng)建了這樣所有的變量都指向了同一個(gè)對(duì)象掀淘。

class Appointment {
    var name:String
    var day:String
    var place:String

    init(name:String, day:String, place:String) {
        self.name = name
        self.day = day
        self.place = place
    }

    func printDetails(label:String) {
        print("\(label) with \(name) on \(day) at \(place)")
    } 
}

var beerMeeting = Appointment(name: "Bob", day: "Mon", place: "Joe's >Bar")
var workMeeting = beerMeeting
workMeeting.name = "Alice"
workMeeting.day = "Fri"
workMeeting.place = "Conference Rm 2"
beerMeeting.printDetails("Social")
workMeeting.printDetails("Work")

除了用類關(guān)鍵字旬蟋,同時(shí)還增加了一個(gè)初始化方法。Swift會(huì)為結(jié)構(gòu)體創(chuàng)建一個(gè)默認(rèn)的初始化方法但是類除外革娄。除此之外倾贰,輸出的結(jié)果也會(huì)和上面的結(jié)構(gòu)體有所不同:

Social with Alice on Fri at Conference Rm 2
Work with Alice on Fri at Conference Rm 2

原因是這里只有一個(gè)對(duì)象,而且它們同時(shí)被beerMeeting和workMeeting所引用拦惋。



實(shí)現(xiàn)NSCopying協(xié)議

在面向?qū)ο缶幊汤锓峙湫碌囊媒o已經(jīng)存在的對(duì)象是一個(gè)重要的部分匆浙,但是對(duì)原型模式一點(diǎn)幫助也沒(méi)有。為了實(shí)現(xiàn)對(duì)象的復(fù)制厕妖,F(xiàn)oundation框架定義了NSCopying協(xié)議首尼。


NSCopying協(xié)議定義了copyWithZone方法,當(dāng)對(duì)象被復(fù)制的時(shí)候會(huì)調(diào)用言秸。為了復(fù)制Appointment软能,原型對(duì)象調(diào)用了copy方法(注意不是copyWithZone)。因?yàn)閏opyWithZone方法返回的是一個(gè)AnyObject举畸,所以需要向下轉(zhuǎn)型查排。值得注意的是,實(shí)現(xiàn)NSCopying協(xié)議并沒(méi)有將引用類型轉(zhuǎn)換成了值類型抄沮,所以必須調(diào)用copy方法去復(fù)制原型對(duì)象跋核。如果你僅僅是將原型對(duì)象賦值給了一個(gè)新的變量,那么你只是獲得了一個(gè)新的引用而非一個(gè)新的對(duì)象叛买。


淺拷貝和深拷貝

原型模式的另一個(gè)重要的方面是對(duì)象被復(fù)制的時(shí)候用的是淺拷貝還是深拷貝砂代。請(qǐng)看下面的例子:


又一次,在變量workMeeting上的修改影響了變量beerMeeting的值率挣。這是因?yàn)槲覀儗lace屬性的類型從String(值類型)變成了Location(引用類型)泊藕,所以NSCopying協(xié)議對(duì)原型對(duì)象的Location屬性創(chuàng)建了一個(gè)新的引用。這就是所謂的淺拷貝,對(duì)象的引用被拷貝了娃圆,而非對(duì)象本身玫锋。


實(shí)現(xiàn)深拷貝

為了實(shí)現(xiàn)深拷貝,不得不讓Location實(shí)現(xiàn)NSCopying協(xié)議和繼承NSObject類讼呢,并實(shí)現(xiàn)copyWithZone方法撩鹿。所有你想實(shí)現(xiàn)深拷貝的引用類型都必須實(shí)現(xiàn)NSCopying協(xié)議,所以你必須對(duì)你原型對(duì)象相關(guān)的那些類重復(fù)這個(gè)操作悦屏,甚至是那些被其他引用關(guān)聯(lián)的引用节沦。



數(shù)組的拷貝

Swift的數(shù)組是通過(guò)結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的,這意味著它是值類型础爬。當(dāng)你將一個(gè)數(shù)組賦值給一個(gè)新的變量時(shí)甫贯,這個(gè)數(shù)組本身和它所包含的任何值類型都將被拷貝。數(shù)組包含的引用類型是淺拷貝看蚜,所以實(shí)際上原型數(shù)組和克隆數(shù)組包含的引用都是指向相同的對(duì)象叫搁。請(qǐng)看下面例子:

作為性能優(yōu)化,Swift的數(shù)組只有去修改了它實(shí)際上才會(huì)被拷貝供炎,這就是延遲拷貝(Lazy Copying)渴逻。這就意味著當(dāng)你僅僅只是讀取拷貝數(shù)組數(shù)據(jù)的時(shí)候,數(shù)組的拷貝就跟引用類型的拷貝一樣音诫;如果你改變拷貝數(shù)組的值惨奕,那么數(shù)組的拷貝就和值類型的拷貝一樣。


實(shí)現(xiàn)數(shù)組的深拷貝

定義了一個(gè)叫做deepCopy的方法用來(lái)接受一個(gè)數(shù)組竭钝,并且用map方法去拷貝這個(gè)數(shù)組梨撞。傳給map方法的閉包用來(lái)檢查對(duì)象是否可以深拷貝,如果可以香罐,調(diào)用copy方法卧波。



原型模式的使用場(chǎng)景

1. 避免開(kāi)銷昂貴的實(shí)例初始化

使用NSCopying協(xié)議允許對(duì)象負(fù)責(zé)拷貝它們自己,這意味著可以避免開(kāi)銷很昂貴的初始化穴吹。請(qǐng)看下面的例子:


每一次創(chuàng)建Sum對(duì)象幽勒,都導(dǎo)致需要分配一個(gè)二維數(shù)組(注意到for循環(huán)執(zhí)行了200次)嗜侮。通過(guò)實(shí)現(xiàn)NSCopying協(xié)議港令,用原型模式可以解決這個(gè)問(wèn)題。再看下面的例子:

上面改變了Sum類的聲明锈颗,讓它繼承了NSObjec類(提供copy方法)顷霹,同時(shí)實(shí)現(xiàn)NSCopying協(xié)議。為了能夠克隆击吱,還添加了一個(gè)新的初始化方法淋淀,用它來(lái)接受一個(gè)cached參數(shù)而并非去生成。我們還給這個(gè)初始化函數(shù)加上了private關(guān)鍵字覆醇,在保證了copyWithZone方法能夠使用它的同時(shí)也阻止了其他組件去使用其他數(shù)據(jù)來(lái)初始化朵纷。


2. 將對(duì)象的創(chuàng)建和使用分離

原型模式允許組件不需要任何信息通過(guò)原型去創(chuàng)建新的對(duì)象炭臭,這意味著可以通過(guò)分離對(duì)象的創(chuàng)建和使用來(lái)減少和原始類(或者結(jié)構(gòu)體)之間的耦合。實(shí)現(xiàn)原型模式的組件并不需要知道它們克隆的原型對(duì)象的類型袍辞,這就使得在那些需要?jiǎng)?chuàng)建新對(duì)象的組件中去限制大量關(guān)于子類的信息成為可能鞋仍。這可能會(huì)有些難以理解,所以請(qǐng)看下面的例子:


上面定義了一個(gè)擁有屬性to和subject的類Message搅吁。還有一個(gè)MessageLogger的類威创,它有一個(gè)存儲(chǔ)Message對(duì)象的方法logMessage和一個(gè)接受閉包作為參數(shù)來(lái)處理存儲(chǔ)的Message的方法processMessages。
問(wèn)題出在我們?yōu)榱藘?yōu)化再利用了已經(jīng)創(chuàng)建的Message對(duì)象谎懦,這導(dǎo)致了MessageLogger里存儲(chǔ)的Message都指向了同一個(gè)對(duì)象肚豺。

解決問(wèn)題(并不是真正的)

如果對(duì)原型模式不熟悉又或者不喜歡NSCopying協(xié)議這種方式,那么你可能這么做:



揭示潛在的問(wèn)題

上面的問(wèn)題算是解決了界拦,但是進(jìn)一步的問(wèn)題出現(xiàn)了吸申。因?yàn)楝F(xiàn)在MessageLogger類希望通過(guò)調(diào)用Message類的初始化方法能創(chuàng)建Message對(duì)象。下面將通過(guò)Message類的子類來(lái)創(chuàng)建一個(gè)更加詳細(xì)的DetailMessage類:


問(wèn)題在于MessageLogger類同時(shí)接受了Message對(duì)象和DetailMessage對(duì)象寞奸,但是卻只是將Message對(duì)象添加到了存儲(chǔ)數(shù)組中呛谜。

解決問(wèn)題(并不是真正的)

不使用原型模式的話,最明顯的解決方法就是讓MessageLogger類注意到現(xiàn)在有兩種不同的對(duì)象了枪萄。請(qǐng)看下面:


這種方法通過(guò)在MessageLogger類里增加Message和Message子類的信息來(lái)解決問(wèn)題隐岛,但是最大的問(wèn)題是每當(dāng)增加一個(gè)Message的子類都不得不去修改MessageLogger類。


應(yīng)用原型模式

應(yīng)用原型模式的優(yōu)點(diǎn)在于對(duì)象能夠保持和它們最開(kāi)始被創(chuàng)建時(shí)完全一樣來(lái)克隆瓷翻,不論是Message對(duì)象或者它的子類對(duì)象聚凹。再創(chuàng)建新的子類或是修改類初始化方法的時(shí)候也不需要再去修改MessageLogger類


總結(jié)

  • 首先齐帚,要避免的是當(dāng)需要深拷貝的時(shí)候卻使用了淺拷貝妒牙。當(dāng)克隆一個(gè)對(duì)象,要仔細(xì)的思考是否需要?jiǎng)?chuàng)建完全分離的對(duì)象的拷貝对妄,或者僅僅是一個(gè)簡(jiǎn)單的引用已經(jīng)足夠了湘今。創(chuàng)建引用相比深拷貝來(lái)說(shuō)又快又簡(jiǎn)單,但是同時(shí)也意味著兩個(gè)或者更多的引用指向了同一個(gè)對(duì)象剪菱。
  • 不要強(qiáng)迫使用一個(gè)原型對(duì)象來(lái)創(chuàng)建所有的克隆摩瞎。這會(huì)導(dǎo)致畸形的代碼結(jié)構(gòu),將原型暴露給了App中的每一個(gè)組件孝常。不要害怕在App的每一個(gè)邏輯章節(jié)中使用復(fù)數(shù)的原型旗们,也不要忘了能通過(guò)克隆來(lái)創(chuàng)建對(duì)象。
  • 實(shí)現(xiàn)原型模式的標(biāo)準(zhǔn)IOS方法是實(shí)現(xiàn)NSCopying協(xié)議和繼承NSObject類构灸。NSCopying協(xié)議對(duì)Swift來(lái)說(shuō)可能并不友好上渴,所以你可能會(huì)創(chuàng)建自己的協(xié)議或者構(gòu)造方法(接受類實(shí)例并拷貝它的初始化方法)。這樣也可以,但是使用NSCopying有一個(gè)好處就是很容易理解并且適用于IOS框架稠氮。不使用標(biāo)準(zhǔn)的協(xié)議將會(huì)限制你創(chuàng)建的原型模式的適用范圍也將會(huì)使得和一些希望實(shí)現(xiàn)NSCopying協(xié)議的第三方代碼的協(xié)作變得很困難曹阔。

Cocoa中的原型模式

原型模式貫穿整個(gè)Cocoa,尤其是在Foundation框架中隔披,你會(huì)發(fā)現(xiàn)很多類都實(shí)現(xiàn)了NSCopying協(xié)議次兆。


Cocoa數(shù)組

尤其感興趣的是NSArray和它的子類NSMutableArray。使用這些類你將經(jīng)常從Objective-C模組接收數(shù)據(jù)锹锰,而且它們和Swif中的數(shù)組也十分不同芥炭。看下面的例子:

import Foundation
class Person : NSObject, NSCopying {
    var name:String
    var country: String
    
    init(name:String, country:String) {
        self.name = name; self.country = country;
    }
    
    func copyWithZone(zone: NSZone) -> AnyObject {
        return Person(name: self.name, country: self.country);
    }
}

var data = NSMutableArray(objects: 10, "iOS", Person(name:"Joe", country:"USA"))
var copiedData = data
data[0] = 20
data[1] = "MacOS"
(data[2] as! Person).name = "Alice"

print("Identity: \(data === copiedData)")

print("0: \(copiedData[0]) 1: \(copiedData[1]) 2: \(copiedData[2].name)")

Tip:NSArray類創(chuàng)建的數(shù)組是不可變的恃慧。NSMutableArray是NSArray的子類园蝠,是可變數(shù)組。

這里我們創(chuàng)建了一個(gè)包含Int痢士,String和一個(gè)Person對(duì)象的NSMutableArray的數(shù)組彪薛。Persion對(duì)象實(shí)現(xiàn)了NSCopying協(xié)議。(跟Swift中數(shù)組有所不同怠蹂,NSMutableArray和NSArray都不是強(qiáng)類型的)
我們將這個(gè)數(shù)組賦值給一個(gè)新的變量copiedData 善延,并且修改了數(shù)組中每個(gè)元素的值。為了完成這個(gè)例子城侧,我們用Swift的恒等式(===)去弄清楚data和copiedData是否引用了同一個(gè)對(duì)象易遣。最后得到下面的結(jié)果:

Identity: true
0: 20 1: MacOS 2: Alice

Swift中的數(shù)組使用結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的,這意味著當(dāng)你將一個(gè)Swift數(shù)組賦值給一個(gè)新的變量時(shí)實(shí)際上是創(chuàng)造了一個(gè)新的數(shù)組并且復(fù)制了數(shù)組中的值嫌佑。但是這里卻不一樣豆茫,相反,改變其中一個(gè)變量的值卻同時(shí)對(duì)兩邊產(chǎn)生了影響屋摇。NSArray和NSMutableArray其實(shí)都是引用類型揩魂,所以和Swift中的Array產(chǎn)生了不同的行為


Cocoa數(shù)組的淺拷貝

我們能應(yīng)用原型模式并且拷貝數(shù)組炮温,當(dāng)然僅僅是淺拷貝火脉。除了copy方法以外,其實(shí)在Foundation類中還有一個(gè)和原型模式相關(guān)的方法mutableCopy柒啤。

Copy:返回一個(gè)NSArray實(shí)例倦挂,不能被修改
mutableCopy:返回一個(gè)NSMutableArray實(shí)例,可以被修改

Cocoa或者Objective-C中的這些方法和Swift中用let和var關(guān)鍵字來(lái)聲明可變和不可變數(shù)組形成了一個(gè)沖突白修。下面將展示如何用mutableCopy方法來(lái)克隆NSMutableArray產(chǎn)生另外一個(gè)對(duì)象妒峦。

...
var data = NSMutableArray(objects: 10, "iOS", Person(name:"Joe", country:"USA"))
var copiedData = data.mutableCopy() as NSArray
...

這樣的結(jié)果就是產(chǎn)生了兩個(gè)不同的NSMutableArray對(duì)象重斑。數(shù)組的元素是淺拷貝兵睛,所以雖然值類型被復(fù)制了但是兩個(gè)數(shù)組引用了同一個(gè)Persion對(duì)象。結(jié)果就是這樣:

Identity: false
0: 10 1: iOS 2: Alice

Cocoa數(shù)組的深拷貝

NSArray和NSMutableArray定義了復(fù)制數(shù)組的構(gòu)造方法,并且可選擇的深拷貝一個(gè)原型數(shù)組的元素祖很。

...
var data = NSMutableArray(objects: 10, "iOS", Person(name:"Joe", country:"USA"))
var copiedData = NSMutableArray(array: data as [AnyObject], copyItems: true)
...

復(fù)制構(gòu)造方法的參數(shù)是一個(gè)原型數(shù)組和一個(gè)指定實(shí)現(xiàn)了NSCopyable(NSCopying)協(xié)議的對(duì)象是否被克隆的布爾類型的值笛丙。這里指定了ture,所以現(xiàn)在引用類型的對(duì)象也被深拷貝了假颇。

Identity: false
0: 10 1: iOS 2: Joe

使用NSCopying屬性標(biāo)注

Swift支持標(biāo)注來(lái)改變屬性的行為胚鸯。其中之一就是@NSCopying,可以應(yīng)用于任何來(lái)源于NSObject并且實(shí)現(xiàn)NSCopying協(xié)議的類型的存儲(chǔ)屬性來(lái)調(diào)用copy方法笨鸡。

import Foundation
class LogItem {
    var from:String?
    @NSCopying var data:NSArray?
}
var dataArray = NSMutableArray(array: [1, 2, 3, 4])
var logitem = LogItem()
logitem.from = "Alice"
logitem.data = dataArray
dataArray[1] = 10

print("Value: \(logitem.data![1])")

這里的data是NSArray類型姜钳,NSArray實(shí)際上繼承了NSObject并且實(shí)現(xiàn)了NSCopying協(xié)議

在這個(gè)例子中,我們定義了一個(gè)含有可選變量from和data的類LogItem形耗。我們給data標(biāo)注上了@NSCopying所以當(dāng)data屬性被設(shè)定的時(shí)候它實(shí)際上是支持淺拷貝的哥桥。所以會(huì)看到下面的結(jié)果:

Value: 2

關(guān)于@NSCopying有一些限制。

  • 首先是在初始化方法里面值被設(shè)定的時(shí)候是不會(huì)克隆的激涤,這也就是為什么我們會(huì)將data定義為可選類型所以我們不用在初始化方法里面去設(shè)定它拟糕。
  • 另一個(gè)是@NSCopying會(huì)去調(diào)用copy方法,甚至當(dāng)對(duì)象支持mutableCopy方法的時(shí)候倦踢。這就意味著當(dāng)我們把NSMutableArray對(duì)象賦值給LogItem的data屬性時(shí)實(shí)際上它被轉(zhuǎn)換成了不可變的NSArray對(duì)象送滞,阻止我們做進(jìn)一步的修改。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辱挥,一起剝皮案震驚了整個(gè)濱河市犁嗅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晤碘,老刑警劉巖愧哟,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異哼蛆,居然都是意外死亡蕊梧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)腮介,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)肥矢,“玉大人,你說(shuō)我怎么就攤上這事叠洗「矢模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵灭抑,是天一觀的道長(zhǎng)十艾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)腾节,這世上最難降的妖魔是什么忘嫉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任荤牍,我火速辦了婚禮,結(jié)果婚禮上庆冕,老公的妹妹穿的比我還像新娘康吵。我一直安慰自己,他們只是感情好访递,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布晦嵌。 她就那樣靜靜地躺著,像睡著了一般拷姿。 火紅的嫁衣襯著肌膚如雪惭载。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天响巢,我揣著相機(jī)與錄音棕兼,去河邊找鬼。 笑死抵乓,一個(gè)胖子當(dāng)著我的面吹牛伴挚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灾炭,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼茎芋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜈出?” 一聲冷哼從身側(cè)響起田弥,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铡原,沒(méi)想到半個(gè)月后偷厦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡燕刻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年只泼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卵洗。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡请唱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出过蹂,到底是詐尸還是另有隱情十绑,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布酷勺,位于F島的核電站本橙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏脆诉。R本人自食惡果不足惜甚亭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一贷币、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狂鞋,春花似錦、人聲如沸潜的。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啰挪。三九已至信不,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亡呵,已是汗流浹背抽活。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锰什,地道東北人下硕。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像汁胆,于是被迫代替她去往敵國(guó)和親梭姓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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