JavaScript設(shè)計(jì)模式之職責(zé)鏈模式

什么是職責(zé)鏈模式毅往?

職責(zé)鏈模式的定義是:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求瞬场,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系野瘦,將這些對(duì)象連成一條鏈躲庄,并沿著這條鏈傳遞該請(qǐng)求查剖,直到有一個(gè)對(duì)象處理它為止。

職責(zé)鏈模式的名字非常形象噪窘,一系列可能會(huì)處理請(qǐng)求的對(duì)象被連接成一條鏈笋庄,請(qǐng)求在這些對(duì)象之間依次傳遞,直到遇到一個(gè)可以處理它的對(duì)象倔监,我們把這些對(duì)象稱(chēng)為鏈中的節(jié)點(diǎn)

image.png

現(xiàn)實(shí)中的職責(zé)鏈模式

職責(zé)鏈模式的例子在現(xiàn)實(shí)中并不難找到直砂,以下就是兩個(gè)常見(jiàn)的跟職責(zé)鏈模式有關(guān)的場(chǎng)景。

  • 如果早高峰能順利擠上公交車(chē)的話浩习,那么估計(jì)這一天都會(huì)過(guò)得很開(kāi)心静暂。因?yàn)楣卉?chē)上人實(shí)在太多了,經(jīng)常上車(chē)后卻找不到售票員在哪谱秽,所以只好把兩塊錢(qián)硬幣往前面遞洽蛀。除非你運(yùn)氣夠好,站在你前面的第一個(gè)人就是售票員疟赊,否則郊供,你的硬幣通常要在N個(gè)人手上傳遞,才能最終到達(dá)售票員的手里近哟。

  • 中學(xué)時(shí)代的期末考試驮审,如果你平時(shí)不太老實(shí),考試時(shí)就會(huì)被安排在第一個(gè)位置。遇到不會(huì)答的題目疯淫,就把題目編號(hào)寫(xiě)在小紙條上往后傳遞地来,坐在后面的同學(xué)如果也不會(huì)答,他就會(huì)把這張小紙條繼續(xù)遞給他后面的人熙掺。

從這兩個(gè)例子中未斑,我們很容易找到職責(zé)鏈模式的最大優(yōu)點(diǎn):請(qǐng)求發(fā)送者只需要知道鏈中的第一個(gè)節(jié)點(diǎn),從而弱化了發(fā)送者和一組接收者之間的強(qiáng)聯(lián)系适掰。如果不使用職責(zé)鏈模式颂碧,那么在公交車(chē)上,我就得先搞清楚誰(shuí)
是售票員类浪,才能把硬幣遞給他载城。同樣,在期末考試中费就,也許我就要先了解同學(xué)中有哪些可以解答這道題诉瓦。

image.png

實(shí)際開(kāi)發(fā)中的職責(zé)鏈模式

假設(shè)我們負(fù)責(zé)一個(gè)售賣(mài)手機(jī)的電商網(wǎng)站,經(jīng)過(guò)分別交納500元定金和200元定金的兩輪預(yù)定后(訂單已在此時(shí)生成)力细,現(xiàn)在已經(jīng)到了正式購(gòu)買(mǎi)的階段睬澡。

公司針對(duì)支付過(guò)定金的用戶有一定的優(yōu)惠政策。在正式購(gòu)買(mǎi)后眠蚂,已經(jīng)支付過(guò)500元定金的用戶會(huì)收到100元的商城優(yōu)惠券煞聪,200元定金的用戶可以收到50元的優(yōu)惠券,而之前沒(méi)有支付定金的用戶只能進(jìn)入普通購(gòu)買(mǎi)模式逝慧,也就是沒(méi)有優(yōu)惠券昔脯,且在庫(kù)存有限的情況下不一定保證能買(mǎi)到。

我們的訂單頁(yè)面是PHP吐出的模板笛臣,在頁(yè)面加載之初云稚,PHP會(huì)傳遞給頁(yè)面幾個(gè)字段。

  • orderType:表示訂單類(lèi)型(定金用戶或者普通購(gòu)買(mǎi)用戶)沈堡,code的值為1的時(shí)候是500元定金用戶静陈,為2的時(shí)候是200元定金用戶,為3的時(shí)候是普通購(gòu)買(mǎi)用戶诞丽。

  • pay:表示用戶是否已經(jīng)支付定金鲸拥,值為true或者false,雖然用戶已經(jīng)下過(guò)500元定金的訂單率拒,但如果他一直沒(méi)有支付定金崩泡,現(xiàn)在只能降級(jí)進(jìn)入普通購(gòu)買(mǎi)模式。

  • stock:表示當(dāng)前用于普通購(gòu)買(mǎi)的手機(jī)庫(kù)存數(shù)量猬膨,已經(jīng)支付過(guò)500元或者200元定金的用戶不受此限制。

下面我們把這個(gè)流程寫(xiě)成代碼:

var order = function( orderType, pay, stock ){
    if ( orderType === 1 ){ // 500元定金購(gòu)買(mǎi)模式
        if ( pay === true ){ // 已支付定金
            console.log( '500元定金預(yù)購(gòu), 得到100優(yōu)惠券' );
        }else{ // 未支付定金,降級(jí)到普通購(gòu)買(mǎi)模式
            if ( stock > 0 ){ // 用于普通購(gòu)買(mǎi)的手機(jī)還有庫(kù)存
                console.log( '普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券' );
            }else{
                console.log( '手機(jī)庫(kù)存不足' );
            }
        }
    }
    else if ( orderType === 2 ){ // 200元定金購(gòu)買(mǎi)模式
        if ( pay === true ){
            console.log( '200元定金預(yù)購(gòu), 得到50優(yōu)惠券' );
        }else{
            if ( stock > 0 ){
                console.log( '普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券' );
            }else{
                console.log( '手機(jī)庫(kù)存不足' );
            }
        }
    }
    else if ( orderType === 3 ){
        if ( stock > 0 ){
            console.log( '普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券' );
        }else{
            console.log( '手機(jī)庫(kù)存不足' );
        }
    }
};
order( 1 , true, 500); // 輸出: 500元定金預(yù)購(gòu), 得到100優(yōu)惠券

雖然我們得到了意料中的運(yùn)行結(jié)果勃痴,但這遠(yuǎn)遠(yuǎn)算不上一段值得夸獎(jiǎng)的代碼谒所。order函數(shù)不僅巨大到難以閱讀,而且需要經(jīng)常進(jìn)行修改沛申。雖然目前項(xiàng)目能正常運(yùn)行劣领,但接下來(lái)的維護(hù)工作無(wú)疑是個(gè)夢(mèng)魘。

用職責(zé)鏈模式重構(gòu)代碼

現(xiàn)在我們采用職責(zé)鏈模式重構(gòu)這段代碼铁材,先把500元訂單尖淘、200元訂單以及普通購(gòu)買(mǎi)分成3個(gè)函數(shù)。

接下來(lái)把orderType著觉、pay村生、stock這3個(gè)字段當(dāng)作參數(shù)傳遞給500元訂單函數(shù),如果該函數(shù)不符合處理?xiàng)l件饼丘,則把這個(gè)請(qǐng)求傳遞給后面的200元訂單函數(shù)趁桃,如果200元訂單函數(shù)依然不能處理該請(qǐng)求,則繼續(xù)傳遞請(qǐng)求給普通購(gòu)買(mǎi)函數(shù)肄鸽,代碼如下:

// 500元訂單
var order500 = function( orderType, pay, stock ){
    if ( orderType === 1 && pay === true ){
        console.log( '500元定金預(yù)購(gòu), 得到100優(yōu)惠券' );
    }else{
        order200( orderType, pay, stock ); // 將請(qǐng)求傳遞給200元訂單
    }
};
// 200元訂單
var order200 = function( orderType, pay, stock ){
    if ( orderType === 2 && pay === true ){
        console.log( '200元定金預(yù)購(gòu), 得到50優(yōu)惠券' );
    }else{
        orderNormal( orderType, pay, stock ); // 將請(qǐng)求傳遞給普通訂單
    }
};
// 普通購(gòu)買(mǎi)訂單
var orderNormal = function( orderType, pay, stock ){
    if ( stock > 0 ){
        console.log( '普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券' );
    }else{
        console.log( '手機(jī)庫(kù)存不足' );
    }
};
// 測(cè)試結(jié)果:
order500( 1 , true, 500); // 輸出:500元定金預(yù)購(gòu), 得到100優(yōu)惠券
order500( 1, false, 500 ); // 輸出:普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券
order500( 2, true, 500 ); // 輸出:200元定金預(yù)購(gòu), 得到50優(yōu)惠券
order500( 3, false, 500 ); // 輸出:普通購(gòu)買(mǎi), 無(wú)優(yōu)惠券
order500( 3, false, 0 ); // 輸出:手機(jī)庫(kù)存不足

可以看到卫病,執(zhí)行結(jié)果和前面那個(gè)巨大的order函數(shù)完全一樣,但是代碼的結(jié)構(gòu)已經(jīng)清晰了很多典徘,我們把一個(gè)大函數(shù)拆分了3個(gè)小函數(shù)蟀苛,去掉了許多嵌套的條件分支語(yǔ)句。

目前已經(jīng)有了不小的進(jìn)步逮诲,但我們不會(huì)滿足于此帜平,雖然已經(jīng)把大函數(shù)拆分成了互不影響的3個(gè)小函數(shù),但可以看到汛骂,請(qǐng)求在鏈條傳遞中的順序非常僵硬罕模,傳遞請(qǐng)求的代碼被耦合在了業(yè)務(wù)函數(shù)之中:

var order500 = function( orderType, pay, stock ){
    if ( orderType === 1 && pay === true ){
        console.log( '500元定金預(yù)購(gòu), 得到100優(yōu)惠券' );
    }else{
        order200( orderType, pay, stock );
        // order200和order500耦合在一起
    }
};

這依然是違反開(kāi)放-封閉原則的,如果有天我們要增加300元預(yù)訂或者去掉200元預(yù)訂帘瞭,意味著就必須改動(dòng)這些業(yè)務(wù)函數(shù)內(nèi)部淑掌。就像一根環(huán)環(huán)相扣打了死結(jié)的鏈條,如果要增加蝶念、拆除或者移動(dòng)一個(gè)節(jié)點(diǎn)抛腕,就必須得先
砸爛這根鏈條。

靈活可拆分的職責(zé)鏈節(jié)點(diǎn)

本節(jié)我們采用一種更靈活的方式媒殉,來(lái)改進(jìn)上面的職責(zé)鏈模式担敌,目標(biāo)是讓鏈中的各個(gè)節(jié)點(diǎn)可以靈活拆分和重組。

首先需要改寫(xiě)一下分別表示3種購(gòu)買(mǎi)模式的節(jié)點(diǎn)函數(shù)廷蓉,我們約定全封,如果某個(gè)節(jié)點(diǎn)不能處理請(qǐng)求,則返回一個(gè)特定的字符串'nextSuccessor'來(lái)表示該請(qǐng)求需要繼續(xù)往后面?zhèn)鬟f:

var order500 = function( orderType, pay, stock ){
    if ( orderType === 1 && pay === true ){
        console.log( '500元定金預(yù)購(gòu),得到100優(yōu)惠券' );
    }else{
        return 'nextSuccessor'; // 我不知道下一個(gè)節(jié)點(diǎn)是誰(shuí)刹悴,反正把請(qǐng)求往后面?zhèn)鬟f
    }
};
var order200 = function( orderType, pay, stock ){
    if ( orderType === 2 && pay === true ){
        console.log( '200元定金預(yù)購(gòu)行楞,得到50優(yōu)惠券' );
    }else{
        return 'nextSuccessor'; // 我不知道下一個(gè)節(jié)點(diǎn)是誰(shuí),反正把請(qǐng)求往后面?zhèn)鬟f
    }
};
var orderNormal = function( orderType, pay, stock ){
    if ( stock > 0 ){
        console.log( '普通購(gòu)買(mǎi)土匀,無(wú)優(yōu)惠券' );
    }else{
        console.log( '手機(jī)庫(kù)存不足' );
    }
};

接下來(lái)需要把函數(shù)包裝進(jìn)職責(zé)鏈節(jié)點(diǎn)子房,我們定義一個(gè)構(gòu)造函數(shù)Chain,在new Chain的時(shí)候傳遞的參數(shù)即為需要被包裝的函數(shù)就轧, 同時(shí)它還擁有一個(gè)實(shí)例屬性this.successor证杭,表示在鏈中的下一個(gè)節(jié)點(diǎn)。

此外Chain的prototype中還有兩個(gè)函數(shù)妒御,它們的作用如下所示:

// Chain.prototype.setNextSuccessor 指定在鏈中的下一個(gè)節(jié)點(diǎn)
// Chain.prototype.passRequest 傳遞請(qǐng)求給某個(gè)節(jié)點(diǎn)
var Chain = function( fn ){
    this.fn = fn;
    this.successor = null;
};
Chain.prototype.setNextSuccessor = function( successor ){
    return this.successor = successor;
};
Chain.prototype.passRequest = function(){
    var ret = this.fn.apply( this, arguments );
    if ( ret === 'nextSuccessor' ){
        return this.successor && this.successor.passRequest.apply( this.successor, arguments );
    }
    return ret;
};

現(xiàn)在我們把3個(gè)訂單函數(shù)分別包裝成職責(zé)鏈的節(jié)點(diǎn):

var chainOrder500 = new Chain( order500 );
var chainOrder200 = new Chain( order200 );
var chainOrderNormal = new Chain( orderNormal )

然后指定節(jié)點(diǎn)在職責(zé)鏈中的順序:

chainOrder500.setNextSuccessor( chainOrder200 );
chainOrder200.setNextSuccessor( chainOrderNormal );

最后把請(qǐng)求傳遞給第一個(gè)節(jié)點(diǎn):

chainOrder500.passRequest( 1, true, 500 ); // 輸出:500元定金預(yù)購(gòu)解愤,得到100優(yōu)惠券
chainOrder500.passRequest( 2, true, 500 ); // 輸出:200元定金預(yù)購(gòu),得到50優(yōu)惠券
chainOrder500.passRequest( 3, true, 500 ); // 輸出:普通購(gòu)買(mǎi)携丁,無(wú)優(yōu)惠券
chainOrder500.passRequest( 1, false, 0 ); // 輸出:手機(jī)庫(kù)存不足

通過(guò)改進(jìn)琢歇,我們可以自由靈活地增加、移除和修改鏈中的節(jié)點(diǎn)順序梦鉴,假如某天網(wǎng)站運(yùn)營(yíng)人員又想出了支持300元定金購(gòu)買(mǎi)李茫,那我們就在該鏈中增加一個(gè)節(jié)點(diǎn)即可:

var order300 = function(){
// 具體實(shí)現(xiàn)略
};
chainOrder300= new Chain( order300 );
chainOrder500.setNextSuccessor( chainOrder300);
chainOrder300.setNextSuccessor( chainOrder200);

對(duì)于程序員來(lái)說(shuō),我們總是喜歡去改動(dòng)那些相對(duì)容易改動(dòng)的地方肥橙,就像改動(dòng)框架的配置文件遠(yuǎn)比改動(dòng)框架的源代碼簡(jiǎn)單得多魄宏。在這里完全不用理會(huì)原來(lái)的訂單函數(shù)代碼,我們要做的只是增加一個(gè)節(jié)點(diǎn)存筏,然后重新設(shè)
置鏈中相關(guān)節(jié)點(diǎn)的順序宠互。

異步的職責(zé)鏈

在上一節(jié)的職責(zé)鏈模式中,我們讓每個(gè)節(jié)點(diǎn)函數(shù)同步返回一個(gè)特定的值"nextSuccessor"椭坚,來(lái)表示是否把請(qǐng)求傳遞給下一個(gè)節(jié)點(diǎn)予跌。而在現(xiàn)實(shí)開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到一些異步的問(wèn)題善茎,比如我們要在節(jié)點(diǎn)函數(shù)中
發(fā)起一個(gè)ajax異步請(qǐng)求券册,異步請(qǐng)求返回的結(jié)果才能決定是否繼續(xù)在職責(zé)鏈中passRequest。

這時(shí)候讓節(jié)點(diǎn)函數(shù)同步返回"nextSuccessor"已經(jīng)沒(méi)有意義了垂涯,所以要給Chain類(lèi)再增加一個(gè)原型方法Chain.prototype.next烁焙,表示手動(dòng)傳遞請(qǐng)求給職責(zé)鏈中的下一個(gè)節(jié)點(diǎn):

Chain.prototype.next= function(){
    return this.successor && this.successor.passRequest.apply( this.successor, arguments );
};

來(lái)看一個(gè)異步職責(zé)鏈的例子:

var fn1 = new Chain(function(){
    console.log( 1 );
    return 'nextSuccessor';
});
var fn2 = new Chain(function(){
    console.log( 2 );
    var self = this;
    setTimeout(function(){
        self.next();
    }, 1000 );
});
var fn3 = new Chain(function(){
    console.log( 3 );
});
fn1.setNextSuccessor( fn2 ).setNextSuccessor( fn3 );
fn1.passRequest();

職責(zé)鏈模式的優(yōu)缺點(diǎn)

前面已經(jīng)說(shuō)過(guò),職責(zé)鏈模式的最大優(yōu)點(diǎn)就是解耦了請(qǐng)求發(fā)送者和N個(gè)接收者之間的復(fù)雜關(guān)系耕赘,由于不知道鏈中的哪個(gè)節(jié)點(diǎn)可以處理你發(fā)出的請(qǐng)求骄蝇,所以你只需把請(qǐng)求傳遞給第一個(gè)節(jié)點(diǎn)即可

職責(zé)鏈模式還有一個(gè)優(yōu)點(diǎn),那就是可以手動(dòng)指定起始節(jié)點(diǎn)操骡,請(qǐng)求并不是非得從鏈中的第一個(gè)節(jié)點(diǎn)開(kāi)始傳遞九火。比如在公交車(chē)的例子中赚窃,如果我明確在我前面的第一個(gè)人不是售票員,那我當(dāng)然可以越過(guò)他把公交卡遞給他前面的人吃既,這樣可以減少請(qǐng)求在鏈中的傳遞次數(shù)考榨,更快地找到合適的請(qǐng)求接受者跨细。這在普通的條件分支語(yǔ)句下是做不到的鹦倚,我們沒(méi)有辦法讓請(qǐng)求越過(guò)某一個(gè)if判斷。

用AOP實(shí)現(xiàn)職責(zé)鏈

在之前的職責(zé)鏈實(shí)現(xiàn)中冀惭,我們利用了一個(gè)Chain類(lèi)來(lái)把普通函數(shù)包裝成職責(zé)鏈的節(jié)點(diǎn)震叙。其實(shí)利用JavaScript的函數(shù)式特性,有一種更加方便的方法來(lái)創(chuàng)建職責(zé)鏈散休。

下面我們改寫(xiě)一下Function.prototype.after函數(shù)媒楼,使得第一個(gè)函數(shù)返回'nextSuccessor'時(shí),將請(qǐng)求繼續(xù)傳遞給下一個(gè)函數(shù)戚丸,無(wú)論是返回字符串'nextSuccessor'或者false都只是一個(gè)約定划址,當(dāng)然在這里我們也可以讓函數(shù)返回false表示傳遞請(qǐng)求,選擇'nextSuccessor'字符串是因?yàn)樗雌饋?lái)更能表達(dá)我們的目的限府,代碼如下:

Function.prototype.after = function( fn ){
    var self = this;
    return function(){
        var ret = self.apply( this, arguments );
        if ( ret === 'nextSuccessor' ){
            return fn.apply( this, arguments );
        }
        return ret;
    }
};
var order = order500yuan.after( order200yuan ).after( orderNormal );
order( 1, true, 500 ); // 輸出:500元定金預(yù)購(gòu)夺颤,得到100優(yōu)惠券
order( 2, true, 500 ); // 輸出:200元定金預(yù)購(gòu),得到50優(yōu)惠券
order( 1, false, 500 ); // 輸出:普通購(gòu)買(mǎi)胁勺,無(wú)優(yōu)惠券

用AOP來(lái)實(shí)現(xiàn)職責(zé)鏈既簡(jiǎn)單又巧妙世澜,但這種把函數(shù)疊在一起的方式,同時(shí)也疊加了函數(shù)的作用域署穗,如果鏈條太長(zhǎng)的話寥裂,也會(huì)對(duì)性能有較大的影響。

小結(jié)

在JavaScript開(kāi)發(fā)中案疲,職責(zé)鏈模式是最容易被忽視的模式之一封恰。實(shí)際上只要運(yùn)用得當(dāng),職責(zé)鏈模式可以很好地幫助我們管理代碼褐啡,降低發(fā)起請(qǐng)的對(duì)象和處理請(qǐng)求的對(duì)象之間的耦合性诺舔。職責(zé)鏈中的節(jié)點(diǎn)數(shù)量和順序是可以自由變化的,我們可以在運(yùn)行時(shí)決定鏈中包含哪些節(jié)點(diǎn)春贸。

無(wú)論是作用域鏈混萝、原型鏈,還是DOM節(jié)點(diǎn)中的事件冒泡萍恕,我們都能從中找到職責(zé)鏈模式的影子逸嘀。職責(zé)鏈模式還可以和組合模式結(jié)合在一起,用來(lái)連接部件和父部件允粤,或是提高組合對(duì)象的效率崭倘。學(xué)會(huì)使用職責(zé)鏈模
式翼岁,相信在以后的代碼編寫(xiě)中,將會(huì)對(duì)你大有裨益司光。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琅坡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子残家,更是在濱河造成了極大的恐慌榆俺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坞淮,死亡現(xiàn)場(chǎng)離奇詭異茴晋,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)回窘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)诺擅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人啡直,你說(shuō)我怎么就攤上這事烁涌。” “怎么了酒觅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵撮执,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我阐滩,道長(zhǎng)二打,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任掂榔,我火速辦了婚禮间校,結(jié)果婚禮上寨昙,老公的妹妹穿的比我還像新娘鳖宾。我一直安慰自己光羞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布穴豫。 她就那樣靜靜地躺著凡简,像睡著了一般。 火紅的嫁衣襯著肌膚如雪精肃。 梳的紋絲不亂的頭發(fā)上秤涩,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音司抱,去河邊找鬼筐眷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛习柠,可吹牛的內(nèi)容都是我干的匀谣。 我是一名探鬼主播照棋,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼武翎!你這毒婦竟也來(lái)了烈炭?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宝恶,失蹤者是張志新(化名)和其女友劉穎符隙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卑惜,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膏执,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了露久。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡欺栗,死狀恐怖毫痕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迟几,我是刑警寧澤消请,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站类腮,受9級(jí)特大地震影響臊泰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚜枢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一缸逃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厂抽,春花似錦需频、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至藐守,卻和暖如春挪丢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卢厂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工乾蓬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人足淆。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓巢块,卻偏偏與公主長(zhǎng)得像礁阁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子族奢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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