設(shè)計模式系列9--狀態(tài)模式

image

今天我們來做一個糖果機吧,用戶只需要投入25美分孵户,就可以購買糖果了环揽,具體的構(gòu)造如下圖所示:

image

每個圓圈都表示一種狀態(tài),而每個箭頭都表示一種動作吨拗,這些狀態(tài)隨著不同動作的進行就可以不斷切換满哪。從圖中可以看到我們有四種狀態(tài)和四種動作婿斥,那么廢話不多說,下面我們就來看看具體的代碼實現(xiàn)哨鸭。

#import "gumabllMachines.h"

typedef enum : NSUInteger {
    sold_out,          //糖果賣完了
    no_quarter,        //沒有硬幣
    has_quarter,       //有硬幣
    sold               //售出糖果
}gumabllMachineState;

@interface gumabllMachines ()
@property(assign,nonatomic)gumabllMachineState state;
@property(assign,nonatomic)NSInteger gumabllCount;
@end


@implementation gumabllMachines

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.gumabllCount = 10;
    }
    return self;
}


//投入硬幣
-(void)insertQuarter{
    if(self.state == has_quarter){
        NSLog(@"不要重復投幣");
    
    }else if (self.state == no_quarter){
        self.state = has_quarter;
        NSLog(@"你投入了一枚硬幣");
    
    }else if (self.state == sold_out){
        NSLog(@"你不能投幣了民宿,糖果已經(jīng)賣完");
    
    }else if (self.state == sold){
        NSLog(@"請等待,我們正在售出糖果");
    }
}


//退出硬幣
-(void)ejectQuarter{
    if(self.state == has_quarter){
        NSLog(@"正在為你退出硬幣");
        self.state = no_quarter;
        
    }else if (self.state == no_quarter){
        NSLog(@"你沒有投入硬幣像鸡,不能退幣");
        
    }else if (self.state == sold_out){
        NSLog(@"不能退幣活鹰,你還沒有投入硬幣");
        
    }else if (self.state == sold){
        NSLog(@"不能退幣,你已經(jīng)轉(zhuǎn)動曲柄只估,購買了糖果");
    }
}

//退出硬幣
-(void)turnCrank{
    if(self.state == has_quarter){
        NSLog(@"不要重復轉(zhuǎn)動曲柄");
        
    }else if (self.state == no_quarter){
        NSLog(@"請投入硬幣");
        
    }else if (self.state == sold_out){
        NSLog(@"沒有糖果啦");
        
    }else if (self.state == sold){
        NSLog(@"正在售出糖果志群,請稍后...");
        self.state = sold;
        [self turnCrank];
    }
}


//售出糖果
-(void)dispense{
    if(self.state == has_quarter){
        self.gumabllCount --;
        if (self.gumabllCount > 0) {
            NSLog(@"糖果正在售出");
            self.state = no_quarter;
        }else{
            self.state = sold_out;
            NSLog(@"不好意思,糖果賣完了");
        }
        
    }else if (self.state == no_quarter){
        NSLog(@"沒有糖果售出");
        
    }else if (self.state == sold_out){
        NSLog(@"沒有糖果售出");
        
    }else if (self.state == sold){
        NSLog(@"沒有糖果售出");
    }

}


@end

上面的代碼可以解決我們目前的問題仅乓,但是該來的還是來了:需求改了赖舟。我們要增加一種狀態(tài):當轉(zhuǎn)到曲柄的時候蓬戚,有10%的幾率會掉下來兩顆糖果夸楣。此時的糖果機如下圖所示:

image

現(xiàn)在多了一種狀態(tài)--贏家,那么就必須在上面的四個方法里面都加上這個狀態(tài)判斷子漩,如果哪天要修改某種狀態(tài)豫喧,那么又必須在四個方法里面一個個的改,簡直不要太麻煩了幢泼。

那怎么解決呢紧显?

仔細分析上面的代碼和圖,我們發(fā)現(xiàn)每次修改了狀態(tài)缕棵,我們都必須修改原有代碼孵班,是因為原有的代碼和狀態(tài)混在一起了,那把這些狀態(tài)獨立出來成為一個個的類不就行了嗎招驴?這樣不管以后增加還是修改狀態(tài)只需要修改單獨的狀態(tài)類就行了篙程,原來的邏輯代碼不需要做任何更改。

上面的代碼是使用動作來進行分類别厘,一個動作方法里面分為四種狀態(tài)虱饿,但是狀態(tài)是需要經(jīng)常修改的,所以導致每次狀態(tài)的修改都需要修改每個動作方法触趴,所以為了避免這樣的情況發(fā)生氮发,我們需要被狀態(tài)單獨出去成為一個類。如果狀態(tài)是固定的冗懦,而動作是經(jīng)常變化的爽冕,那么就可以考慮把動作單獨出去成為一個類。其實終極目標就是:把變化和不變化的分離開來披蕉,把變化的部分單獨封裝起來颈畸,使之單獨變化前塔,不會影響不變化的部分。

下面我們就來看看具體的代碼實現(xiàn)


代碼實現(xiàn)

1承冰、定義狀態(tài)類的接口

我們需要定義一個接口华弓,接口里面包括上面的四種動作,每個狀態(tài)類都需要實現(xiàn)這四個方法

#import <Foundation/Foundation.h>

@protocol stateInterface <NSObject>
@required
-(void)insertQuarter;
-(void)ejectQuarter;
-(void)trunCrank;
-(void)dispense;

@end


2困乒、定義四種狀態(tài)

現(xiàn)在我們要實現(xiàn)糖果機的四種狀態(tài)寂屏,我們把這些狀態(tài)都提取出來,單獨成類娜搂,每個狀態(tài)都會實現(xiàn)上面接口的四個動作

沒有25分錢的狀態(tài)

#import <Foundation/Foundation.h>
#import "stateInterface.h"
#import "gumabllMachine.h"

@interface noQuarterState : NSObject<stateInterface>
@property(strong,nonatomic)gumabllMachine *machine;
- (instancetype)initWithMachine:(gumabllMachine *)machine;
@end


===============

#import "noQuarterState.h"

@implementation noQuarterState
- (instancetype)initWithMachine:(gumabllMachine *)machine
{
    self = [super init];
    if (self) {
        self.machine = machine;
    }
    return self;
}

-(void)insertQuarter{
    NSLog(@"你塞入了一枚硬幣");
    self.machine.state = self.machine.hasQuarterState;
}

-(void)ejectQuarter{
    NSLog(@"你沒有塞入一枚硬幣迁霎,不能退錢");
}


-(void)trunCrank{
    NSLog(@"你按了購買按鈕,但是你沒有塞入硬幣百宇,請塞入硬幣");

}
-(void)dispense{
    NSLog(@"你要買一個糖果考廉,但是你沒有塞入硬幣,請先付款");

}


@end

有25分錢的狀態(tài)

#import <Foundation/Foundation.h>
#import "stateInterface.h"
#import "gumabllMachine.h"

@interface hasQUarterState : NSObject<stateInterface>
@property(strong,nonatomic)gumabllMachine *machine;
- (instancetype)initWithMachine:(gumabllMachine *)machine;

@end

===========

#import "hasQUarterState.h"

@implementation hasQUarterState
- (instancetype)initWithMachine:(gumabllMachine *)machine
{
    self = [super init];
    if (self) {
        self.machine = machine;
    }
    return self;
}

-(void)insertQuarter{
    NSLog(@"你已經(jīng)塞入了一枚硬幣携御,不要重復投幣");
}

-(void)ejectQuarter{
    NSLog(@"硬幣即將推出");
    self.machine.state = self.machine.noQuarterState;

}


-(void)trunCrank{
    NSLog(@"你選擇購買糖果昌粤,處理中....");
    self.machine.state = self.machine.soldingState;

    
}
-(void)dispense{
    NSLog(@"請先選擇購買糖果");
}

@end


售賣中的狀態(tài)

#import <Foundation/Foundation.h>
#import "stateInterface.h"
#import "gumabllMachine.h"

@interface soldingState : NSObject<stateInterface>
@property(strong,nonatomic)gumabllMachine *machine;
- (instancetype)initWithMachine:(gumabllMachine *)machine;

@end

=====================
#import "soldingState.h"

@implementation soldingState
- (instancetype)initWithMachine:(gumabllMachine *)machine
{
    self = [super init];
    if (self) {
        self.machine = machine;
    }
    return self;
}

-(void)insertQuarter{
    NSLog(@"請等待我們正在出貨,不要重復投幣...");
}

-(void)ejectQuarter{
    NSLog(@"對不起啄刹,你已經(jīng)購買了糖果涮坐,不能退款");
    
}


-(void)trunCrank{
    NSLog(@"重復點擊按鈕,不會得到更多糖果哦");
    
}
-(void)dispense{
    if (self.machine.count > 0) {
        self.machine.count --;
        self.machine.state = self.machine.noQuarterState;
        NSLog(@"糖果已經(jīng)售出");
        NSLog(@"糖果還剩下:%zd",self.machine.count);
    }else{
        NSLog(@"抱歉誓军,沒有糖果了袱讹,如果需要退款,請點擊退幣按鈕");
        self.machine.state = self.machine.soldOutState;
    }
    
}

@end


糖果售罄的狀態(tài)

#import <Foundation/Foundation.h>
#import "stateInterface.h"
#import "gumabllMachine.h"

@interface soldOutState : NSObject<stateInterface>
@property(strong,nonatomic)gumabllMachine *machine;
- (instancetype)initWithMachine:(gumabllMachine *)machine;

@end

===========================

#import "soldOutState.h"

@implementation soldOutState
- (instancetype)initWithMachine:(gumabllMachine *)machine
{
    self = [super init];
    if (self) {
        self.machine = machine;
    }
    return self;
}

-(void)insertQuarter{
    NSLog(@"沒有糖果啦昵时,不要投幣捷雕,請下次再來");
}

-(void)ejectQuarter{
    NSLog(@"即將為你退款...");
    
}


-(void)trunCrank{
    NSLog(@"沒有糖果哦");
    
}
-(void)dispense{
    NSLog(@"沒有糖果啦");
}

@end

3、實現(xiàn)糖果機

糖果機類主要干兩件事:

  • 公開方法壹甥,給客戶端操作救巷,公開的四種方法分別對應四種動作
  • 公開并初始化四種狀態(tài),供狀態(tài)類切換狀態(tài)
#import <Foundation/Foundation.h>
#import "stateInterface.h"

@interface gumabllMachine : NSObject
-(void)setState:(id<stateInterface>)state;
@property(strong,nonatomic)id<stateInterface> state;
@property(strong,nonatomic)id<stateInterface> soldOutState;
@property(strong,nonatomic)id<stateInterface> noQuarterState;
@property(strong,nonatomic)id<stateInterface> hasQuarterState;
@property(strong,nonatomic)id<stateInterface> soldingState;
@property(assign,nonatomic)NSInteger count;

- (instancetype)initWithGumabllCount:(NSInteger)count;
-(void)machineInsertQuarter;
-(void)machineEjectQuarter;
-(void)machinetrunCrank;
-(void)machineDispense;


@end


=========================

#import "gumabllMachine.h"
#import "noQuarterState.h"
#import "hasQUarterState.h"
#import "soldingState.h"
#import "soldOutState.h"


@implementation gumabllMachine
- (instancetype)initWithGumabllCount:(NSInteger)count
{
    self = [super init];
    if (self) {
        self.count =count;
        self.noQuarterState = [[noQuarterState alloc]initWithMachine:self];
        self.hasQuarterState = [[hasQUarterState alloc]initWithMachine:self];
        self.soldingState = [[soldingState alloc]initWithMachine:self];
        self.soldOutState = [[soldOutState alloc]initWithMachine:self];
        //初始化狀態(tài)為沒有硬幣狀態(tài)
        if (self.count > 0) self.state = self.noQuarterState;
    }
    return self;
}

//可以發(fā)現(xiàn)此時的四種動作方法都委托給狀態(tài)類去實現(xiàn)了
-(void)machineInsertQuarter{
    [self.state insertQuarter];
}

-(void)machineEjectQuarter{
    [self.state ejectQuarter];
}


-(void)machinetrunCrank{
    [self.state trunCrank];
}

-(void)machineDispense{
    [self.state dispense];
}


@end

4盹廷、客戶端測試

        1征绸、gumabllMachine *machine = [[gumabllMachine alloc]initWithGumabllCount:2];
        2、[machine machineInsertQuarter];
        3俄占、[machine machinetrunCrank];
        4管怠、[machine machineDispense];
        [machine machineEjectQuarter];

輸出如下

2016-12-13 10:42:24.218 狀態(tài)模式[62936:1497982] 你塞入了一枚硬幣
2016-12-13 10:42:24.218 狀態(tài)模式[62936:1497982] 你選擇購買糖果,處理中....
2016-12-13 10:42:24.218 狀態(tài)模式[62936:1497982] 糖果已經(jīng)售出
2016-12-13 10:42:24.219 狀態(tài)模式[62936:1497982] 糖果還剩下:1
2016-12-13 10:42:24.219 狀態(tài)模式[62936:1497982] 你沒有塞入一枚硬幣缸榄,不能退錢
Program ended with exit code: 0

我們使用示意圖來展示下上面的流程

image

上面的流程圖的四個步驟正好對應客戶端測試代碼的四句代碼渤弛,下面來一一分析下

  1. 初始化糖果機,此時糖果機的狀態(tài)時noquarter(沒有25分錢的狀態(tài))
  2. 執(zhí)行糖果機gumabllMachine的動作方法machineInsertQuarter甚带,投入硬幣她肯,此方法把動作委托到當前狀態(tài)類(noQuarterState)去執(zhí)行佳头,跳到noQuarterState類,執(zhí)行insertQuarter方法晴氨,輸出顯示康嘉,并通過引用gumabllMachine類的實例改變當前狀態(tài)為hasQuarterState
  3. 執(zhí)行糖果機gumabllMachine的動作方法machinetrunCrank,此方法把動作委托到當前狀態(tài)類(hasQuarterState)去執(zhí)行籽前,跳到hasQuarterState類亭珍,執(zhí)行trunCrank方法,輸出顯示枝哄,并通過引用gumabllMachine類的實例改變當前狀態(tài)為soldingState
  4. 執(zhí)行糖果機gumabllMachine的動作方法machineDispense肄梨,此方法把動作委托到當前狀態(tài)類(soldingState)去執(zhí)行,跳到soldingState類挠锥,執(zhí)行dispense方法众羡,輸出顯示,并通過引用gumabllMachine類的實例改變當前狀態(tài)為noQuarterState回到第一步的初始狀態(tài)

通過上面的分析我們可以看出兩點:

  1. 糖果機的動作方法全部委托給具體的狀態(tài)類去實現(xiàn)
  2. 狀態(tài)類自身可以切換狀態(tài)

這就是我們今天要講的狀態(tài)模式的兩個作用蓖租,下面來具體看看


定義

允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為粱侣。對象看起來似乎修改了它的類。

我們先來解讀下第一句話菜秦,首先狀態(tài)模式把狀態(tài)單獨分裝成一個個的類甜害,然后把動作委托到當前的狀態(tài)類去執(zhí)行,那么當狀態(tài)改變的時候球昨,即使同一個動作的執(zhí)行結(jié)果也會不同。對比到上面的例子眨攘,對于不同的糖果機狀態(tài)主慰,我們投入25分錢,可能會被接受或者拒絕鲫售。這就是說狀態(tài)改變的時候共螺,行為也會跟著改變,也就是第一句話的意思情竹。

那么第二句話呢藐不?由于狀態(tài)在運行的時候是在不斷變化的,而相同的動作也會隨著狀態(tài)的變化而變化秦效,那么同一個對象gumabllMachine在不同的時刻雏蛮,相同的動作會因為狀態(tài)的不同而出現(xiàn)不同的執(zhí)行結(jié)果,看起來就像是gumabllMachine被改變了(因為一般情況下阱州,如果外在條件不改變挑秉,一個類的相同方法每次執(zhí)行結(jié)果應該相同)。而實際上只是通過切換到不同的狀態(tài)對象來造成gumabllMachine類被改變的假象苔货。

對象的狀態(tài)一般指的是對象實例的屬性的值犀概,對應到上面的例子就是gumabllMachine實例對象的state屬性立哑,行為指的是對象的功能,對應上面的例子就是gumabllMachine的實例的四個公開方法姻灶。狀態(tài)模式的作用是分離狀態(tài)所對應的行為铛绰,每個狀態(tài)都對應相同的行為,但是每個狀態(tài)的相同行為卻有不同的表現(xiàn)形式产喉。對應上面的例子就是每個糖果機狀態(tài)都有四種行為至耻,但是每種行為的表現(xiàn)卻是不同的。這樣通過切換到不同的狀態(tài)镊叁,就可以實現(xiàn)該狀態(tài)下對應的具體行為尘颓,所以說狀態(tài)決定行為。

通過上面的分析可以得知:狀態(tài)模式實現(xiàn)的前提是晦譬,行為不變疤苹,而狀態(tài)不斷變化。


適用性

在如下情況可以考慮采用狀態(tài)模式:

  • 一個對象的行為取決于它的狀態(tài),并且它必須在運行時刻根據(jù)狀態(tài)改變它的行為敛腌。

  • 一個操作中含有龐大的多分支的條件語句,且這些分支依賴于該對象的狀態(tài)卧土。
    這個狀態(tài)通常用一個或多個枚舉常量表示。通常 , 有多個操作包含這一相同的條件結(jié)構(gòu)像樊。 state模式將每一個條件分支放入一個獨立的類中尤莺。這使得你可以根據(jù)對象自身的情況將對 象的狀態(tài)作為一個對象,這一對象可以不依賴于其他對象而獨立變化。


UML結(jié)構(gòu)圖及說明

image

狀態(tài)模式將 與 特 定 狀 態(tài) 相 關(guān) 的 行 為 局 部 化 , 并 且 將 不 同 狀 態(tài) 的 行 為 分 割 開 來 state 模式將所有與一個特定的狀態(tài)相關(guān)的行為都放入一個對象中生棍。因為所有與狀態(tài)相關(guān)的代碼都存在于某 一個 S t a t e 子類中 , 所 以 通 過 定 義 新 的 子 類 可 以 很 容 易 的 增 加 新 的 狀 態(tài) 和 轉(zhuǎn) 換 颤霎。

另一個方法是使用數(shù)據(jù)值定義內(nèi)部狀態(tài)并且讓 C o n t e x t 操 作 來 顯 式 地 檢 查 這 些 數(shù) 據(jù) 。 但 這 樣將會使整個 C o n t e x t 的實現(xiàn)中遍布看起來很相似的條件語句或 c a s e 語 句 涂滴。 增 加 一 個 新 的 狀 態(tài) 可能需要改變?nèi)舾蓚€操作 , 這就使得維護變得復雜了友酱。

S t a t e 模式避免了這個問題 , 但可能會引入另一個問題 , 因 為 該 模 式 將 不 同 狀 態(tài) 的 行 為 分 布在多個 S t a t e 子 類 中 。 這 就 增 加 了 子 類 的 數(shù) 目 , 相 對 于 單 個 類 的 實 現(xiàn) 來 說 不 夠 緊 湊 柔纵。 但 是 如 果 有許多狀態(tài)時這樣的分布實際上更好一些 , 否則需要使用巨大的條件語句缔杉。
正如很長的過程一樣,巨大的條件語句是不受歡迎的。它們形成一大整塊并且使得代碼 不夠清晰,這又使得它們難以修改和擴展搁料。

S t a t e模 式 提 供 了 一 個 更 好 的 方 法 來 組 織 與 特 定 狀 態(tài) 相 關(guān) 的 代 碼 或详。 決 定 狀 態(tài) 轉(zhuǎn) 移 的 邏 輯 不 在 單 塊 的 i f 或 s w i t c h 語句中 , 而 是 分 布 在 S t a t e 子類之間。 將每一個狀態(tài)轉(zhuǎn)換和動作封裝到一個類中,就把著眼點從執(zhí)行狀態(tài)提高到整個對象的狀態(tài)郭计。 這將使代碼結(jié)構(gòu)化并使其意圖更加清晰霸琴。


優(yōu)缺點

  • 簡化應用的邏輯控制

    狀態(tài)模式使用單獨的類來封裝一個狀態(tài)的處理。這樣可以把一個很大的程序控制分割到很多小的單獨的狀態(tài)類中去實現(xiàn)拣宏,這樣把本來著眼于通過行為分類轉(zhuǎn)換到著眼于通過狀態(tài)分類沈贝,對于那種狀態(tài)經(jīng)常變化的程序來說,這樣的改變后勋乾,代碼邏輯更加清晰宋下,也可以消除巨大的if-else判斷語句

  • 更好的分離狀態(tài)和行為

    通過設(shè)置所有狀態(tài)類的公共接口嗡善,定義他們共有的行為,每個狀態(tài)類都實現(xiàn)這些行為但是表現(xiàn)不同学歧,這樣程序只需要設(shè)置合適的狀態(tài)類就可以執(zhí)行行為罩引,從而讓程序只需要關(guān)心狀態(tài)的切換,而不需要關(guān)心狀態(tài)對應的行為枝笨,處理起來更加簡單清晰袁铐。

  • 更好的擴展性

    以后如果新增一個狀態(tài)類,只需要實現(xiàn)公共接口定義的行為即可横浑,然后在需要的地方添加接口剔桨,做到了開閉原則。

  • 更加明了的狀態(tài)切換

    狀態(tài)切換只在一個地方進行(context或者狀態(tài)類中)徙融,狀態(tài)的切換都是通過一個變量來記錄洒缀,這樣就不會造成狀態(tài)切換混亂。


狀態(tài)的維護和轉(zhuǎn)換

有兩種方式來實現(xiàn)狀態(tài)的維護和轉(zhuǎn)換

  1. 在context中
  2. 在每個具體的狀態(tài)類中

上面的例子就是使用了第二種方法欺冀,如果放在context中怎么實現(xiàn)呢树绩?也很簡單,只需要把本來在每個具體的狀態(tài)類中的狀態(tài)轉(zhuǎn)換代碼提取到context中即可隐轩,修改gumabllMachine如下所示饺饭,記得刪除每個狀態(tài)類的狀態(tài)轉(zhuǎn)換代碼


#import "gumabllMachine.h"
#import "noQuarterState.h"
#import "hasQUarterState.h"
#import "soldingState.h"
#import "soldOutState.h"


@implementation gumabllMachine
- (instancetype)initWithGumabllCount:(NSInteger)count
{
    self = [super init];
    if (self) {
        self.count =count;
        self.noQuarterState = [[noQuarterState alloc]initWithMachine:self];
        self.hasQuarterState = [[hasQUarterState alloc]initWithMachine:self];
        self.soldingState = [[soldingState alloc]initWithMachine:self];
        self.soldOutState = [[soldOutState alloc]initWithMachine:self];
        //初始化狀態(tài)為沒有硬幣狀態(tài)
        if (self.count > 0) self.state = self.noQuarterState;
    }
    return self;
}


-(void)machineInsertQuarter{
    [self.state insertQuarter];
    self.state = self.hasQuarterState;

}

-(void)machineEjectQuarter{
    [self.state ejectQuarter];
    self.state = self.noQuarterState;

}


-(void)machinetrunCrank{
    [self.state trunCrank];
    self.state = self.soldingState;

}

-(void)machineDispense{
    [self.state dispense];
    if (self.count > 0) {
        self.state = self.noQuarterState;
    }else{
        self.state = self.soldOutState;
    }

}


@end


Demo下載

狀態(tài)模式Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市职车,隨后出現(xiàn)的幾起案子瘫俊,更是在濱河造成了極大的恐慌,老刑警劉巖提鸟,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件军援,死亡現(xiàn)場離奇詭異,居然都是意外死亡称勋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門涯竟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赡鲜,“玉大人,你說我怎么就攤上這事庐船∫辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵筐钟,是天一觀的道長揩瞪。 經(jīng)常有香客問我,道長篓冲,這世上最難降的妖魔是什么李破? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任宠哄,我火速辦了婚禮,結(jié)果婚禮上嗤攻,老公的妹妹穿的比我還像新娘毛嫉。我一直安慰自己,他們只是感情好妇菱,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布承粤。 她就那樣靜靜地躺著,像睡著了一般闯团。 火紅的嫁衣襯著肌膚如雪辛臊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天房交,我揣著相機與錄音彻舰,去河邊找鬼。 笑死涌萤,一個胖子當著我的面吹牛淹遵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播负溪,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼透揣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了川抡?” 一聲冷哼從身側(cè)響起辐真,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崖堤,沒想到半個月后侍咱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡密幔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年楔脯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胯甩。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡昧廷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出偎箫,到底是詐尸還是另有隱情木柬,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布淹办,位于F島的核電站眉枕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜速挑,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一谤牡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梗摇,春花似錦拓哟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糜烹,卻和暖如春违诗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮蹦。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工诸迟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人愕乎。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓阵苇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親感论。 傳聞我的和親對象是個殘疾皇子绅项,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

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