Head First 設(shè)計模式(3)----裝飾者模式

本文參照《Head First 設(shè)計模式》帖鸦,轉(zhuǎn)載請注明出處
對于整個系列咱筛,我們按照這本書的設(shè)計邏輯,使用情景分析的方式來描述嫌佑,并且穿插使用一些問題豆茫,總結(jié)的方式來講述侨歉。并且所有的開發(fā)源碼,都會托管到github上揩魂。
項目地址:https://github.com/jixiang52002/HFDesignPattern

回顧上一篇文章講解了設(shè)計模式中常用的一種模式------觀察者模式幽邓。并結(jié)合氣象站設(shè)計進行實戰(zhàn)解析,并且從自己設(shè)計到JAVA自帶設(shè)計模式做了講解火脉。想要了解的朋友可以回去回看一下牵舵。
Head First 設(shè)計模式(2)---觀察者(Observer)模式

本章我們會繼續(xù)前面的話題,有關(guān)典型的繼承濫用問題倦挂。這一章會講解如何使用對象組合的方式畸颅,如何在運行時候做裝飾類。在熟悉裝飾技巧后方援,我們能夠在原本不修改任何底層的代碼没炒,卻可以給原有對象賦予新的職能。你會說犯戏,這不就是“裝飾者模式”送火。沒錯,接下來就是裝飾者模式的ShowTime時間笛丙。

1.前言

歡迎來到星巴茲咖啡漾脂,該公司是世界上以擴張速度最快而聞名的咖啡連鎖店。但是最近這家著名的咖啡公司遇到一個巨大的問題胚鸯,因為擴展速度太快了骨稿,他們準(zhǔn)備更新訂單系統(tǒng),以合乎他們的飲料供應(yīng)需求姜钳。

他們本來的設(shè)計方式如下:


Beverage類結(jié)構(gòu)

然后客戶購買咖啡時坦冠,可以要求在其中加入任何調(diào)料,例如:奶茶哥桥,牛奶辙浑,豆?jié){。星巴茲根據(jù)業(yè)務(wù)需求會計算相應(yīng)的費用拟糕。這就要求訂單系統(tǒng)必須考慮到這些調(diào)料的部分判呕。

然后我們就看到他們的第一個嘗試設(shè)計:

各種飲料的類關(guān)系圖

是不是有一種犯了密集恐懼癥的感覺,整完全就是“類爆炸”送滞。
那么我們分析一下侠草,這種設(shè)計方式違反了什么設(shè)計原則?沒錯,違反了以下兩個原則:

第二設(shè)計原則
針對于接口編程犁嗅,不針對實現(xiàn)編程

第三設(shè)計原則
多用組合边涕,少用繼承

那么我們應(yīng)該怎么修改這個設(shè)計呢?

2.利用繼承對Beverage類進行改造

首先,我們考慮對基類Beverage類進行修改功蜓,我們根據(jù)前面“類爆炸”進行分析园爷。主要飲料包含各種調(diào)料(牛奶,豆?jié){式撼,摩卡童社,奶泡。著隆。叠洗。。)旅东。
所以修改后的Beverage類的結(jié)構(gòu)如下:

Beverage帶調(diào)料后的實現(xiàn)

Beverage類具體實現(xiàn)如下:

public class Beverage {
    protected String description;//飲料簡介
    
    protected boolean milk=false;//是否有牛奶
    
    protected boolean soy=false;//是否有豆?jié){
    
    protected boolean cocha=false;//是否有摩卡
    
    protected boolean whip=false;//是否有奶泡
    
    protected double milkCost=1.01;//牛奶價格
    
    protected double soyCost=1.03;//豆?jié){價格
    
    protected double cochaCost=2.23;//摩卡價格
    
    protected double whipCost=0.89;//奶泡價格
    
    
    public String getDescription() {
        return description;
    }


    public void setDescription(String description) {
        this.description = description;
    }


    public boolean hasMilk() {
        return milk;
    }


    public void setMilk(boolean milk) {
        this.milk = milk;
    }


    public boolean hasSoy() {
        return soy;
    }


    public void setSoy(boolean soy) {
        this.soy = soy;
    }


    public boolean hasCocha() {
        return cocha;
    }


    public void setCocha(boolean cocha) {
        this.cocha = cocha;
    }


    public boolean hasWhip() {
        return whip;
    }


    public void setWhip(boolean whip) {
        this.whip = whip;
    }
    
    


    public double getCochaCost() {
        return cochaCost;
    }


    public void setCochaCost(double cochaCost) {
        this.cochaCost = cochaCost;
    }


    public double getWhipCost() {
        return whipCost;
    }


    public void setWhipCost(double whipCost) {
        this.whipCost = whipCost;
    }


   

    public double cost(){
        
        double condiments=0.0;
        if(hasMilk()){//是否需要牛奶
            condiments+=milkCost;
        }
        if(hasSoy()){//是否需要豆?jié){
            condiments+=soyCost;
        }
        if(hasCocha()){//是否需要摩卡
            condiments+=cochaCost;
        }
        if(hasWhip()){//是否需要奶泡
            condiments+=whipCost;
        }
        return condiments;
    }

}

實現(xiàn)其中一個子類DarkRoast:

public class DarkRoast extends Beverage{

    public DarkRoast(){
        description="Most Excellent Dark Roast!";
    }
    
    public double cost(){
        return 1.99+super.cost();
    }
}

看起來很完美,也能滿足現(xiàn)有的業(yè)務(wù)需求十艾,但是仔細思考一下抵代,真的這樣設(shè)計不會出錯?

回答肯定是會出錯忘嫉。

  • 第一荤牍,一旦調(diào)料的價格發(fā)生變化,會導(dǎo)致我們隊原有代碼進行大改庆冕。
  • 第二康吵,一旦出現(xiàn)新的調(diào)料,我們就需要加上新的方法访递,并需要改變超類Beverage類中cost()方法晦嵌。
  • 第三,如果星巴茲咖啡研發(fā)新的飲料拷姿。對于這些飲料而言惭载,某些調(diào)料可能并不合適,但是子類仍然會繼承那些本就不合適的方法响巢,例如我就想要一杯水描滔,加奶泡(hasWhip)就不合適。
  • 第四踪古,如果用戶需要雙倍的摩卡咖啡含长,又應(yīng)該怎么辦呢?

3.開放-關(guān)閉原則

到這里伏穆,我們可以推出最重要的設(shè)計原則之一:

第五設(shè)計原則:
類應(yīng)該對拓展開放拘泞,對修改關(guān)閉。

那么什么是開放蜈出,什么又是關(guān)閉田弥?開放就是允許你使用任何行為來拓展類,如果需求更改(這是無法避免的)铡原,就可以進行拓展偷厦!關(guān)閉在于我們花費很多時間完成開發(fā)商叹,并且已經(jīng)測試發(fā)布,針對后續(xù)更改只泼,我們必須關(guān)閉原有代碼防止被修改剖笙,避免造成已經(jīng)測試發(fā)布的源碼產(chǎn)生新的bug。

綜合上述說法请唱,我們的目標(biāo)在于允許類拓展弥咪,并且在不修改原有代碼的情況下,就可以搭配新的行為十绑。如果能實現(xiàn)這樣的目標(biāo)聚至,帶來的好處將相當(dāng)可觀。在于代碼會具備彈性來應(yīng)對需求改變本橙,可以接受增加新的功能用來實現(xiàn)改變的需求扳躬。沒錯,這就是拓展開放甚亭,修改關(guān)閉贷币。

那么有沒有可以參照的實例可以分析呢?有亏狰,就在第二篇我們介紹觀察者模式時役纹,我們介紹到可以通過增加新的觀察者用來拓展主題,并且無需向原主題進行修改暇唾。

我們是否需要每個模塊都設(shè)計成開放--關(guān)閉原則促脉?不用,也很難辦到(這樣的家伙可以稱為“不用設(shè)計模式會死病”)策州。因為想要完全符合開放-關(guān)閉原則嘲叔,會引入大量的抽象層,增加原有代碼的復(fù)雜度抽活。我們應(yīng)該區(qū)分設(shè)計中可能改變的部分和不改變的部分(第一設(shè)計原則)硫戈,針對改變部分使用開放--關(guān)閉原則。

4.裝飾模式

這里下硕,就到了開放--關(guān)閉原則的運用模式-----裝飾者模式丁逝。首先我們還是從星巴茲咖啡的案例來做一個簡單的分析。
分析之前兩個版本(類爆炸 和 繼承大法)的實現(xiàn)方式梭姓,并不能適用于所有的子類霜幼。

這就需要一個新的設(shè)計思路。這里誉尖,我們將以飲料為主罪既,然后運行的時候以飲料來“裝飾”飲料。舉個栗子,如果用戶需要摩卡和奶泡深焙咖啡琢感,那么要做的是:

  • 拿一個深焙咖啡(DarkRosat)對象

  • 以摩卡(Mocha)對象裝飾它

  • 以奶泡(Whip)對象裝飾它

  • 調(diào)用cost()方法丢间,并依賴委托(delegate)將調(diào)料的價錢加上去。

具體的實現(xiàn)我們用一張圖來展示

  • 首先我們構(gòu)建DarkRoast對象


    DarkRoast對象
  • 假如顧客需要摩卡(Mocha)驹针,再建立一個Mocha對象烘挫,并用DarkRoast對象包起來。


    Mocha對象
  • 如果顧客也想要奶泡(Whip),就建立一個Whip裝飾者柬甥,并將它用Mocha對象包起來饮六。


    Mocha對象
  • 最后運算客戶的賬單的時候,通過最外層的裝飾者Whip的cost()就可以辦得到苛蒲。Whip的cost()會委托他的裝飾對象(Mocha)計算出價格卤橄,再加上奶泡(Whip)的價格。

計算用戶的賬單

通過對星巴茲咖啡的設(shè)計方案分析臂外,我們可以發(fā)現(xiàn)虽风,所有的裝飾類都具備以下幾個特點:

  • 裝飾者和被裝飾對象有相同的超類型。

  • 你可以用一個或多個裝飾者包裝一個對象寄月。

  • 既然裝飾者和被裝飾對象有相同的超類型,所以在任何需要原始對象(被包裝的)的場合无牵,可以用裝飾過的對象代替它漾肮。

  • 裝飾者可以在所委托被裝飾者的行為之前與/或之后,加上自己的行為茎毁,以達到特定的目的克懊。

  • 對象可以在任何時候被裝飾,所以可以在運行時動態(tài)地七蜘、不限量地用你喜歡的裝飾者來裝飾對象

什么是裝飾模式呢谭溉?我們首先來看看裝飾模式的定義:

裝飾者模式動態(tài)地將責(zé)任附加到對象上。
若要擴展功能橡卤,裝飾者提供了比繼承更有彈性
的替代方案扮念。

定義雖然已經(jīng)定義了裝飾者模式的“角色”,但是未說明怎么在我們的實現(xiàn)中如何使用它們碧库。我們繼續(xù)在星巴茲咖啡中來熟悉相關(guān)的操作柜与。

裝飾者模式類圖

其中裝飾者層級可以無限發(fā)展下去,不是如圖中一般兩層關(guān)系嵌灰。并且組件也并非只有一個弄匕,可以存在多個。

現(xiàn)在我們就在星巴茲咖啡里運用裝飾者模式:


使用裝飾模式的星巴茲咖啡

到這里沽瞭,我們隊裝飾者模式已經(jīng)有了一個基本的認識迁匠。那么我們已經(jīng)解決了上面提到的四個問題:

  • 第一,一旦調(diào)料的價格發(fā)生變化,會導(dǎo)致我們隊原有代碼進行大改城丧。
  • 第二延曙,一旦出現(xiàn)新的調(diào)料,我們就需要加上新的方法芙贫,并需要改變超類Beverage類中cost()方法搂鲫。
  • 第三,如果星巴茲咖啡研發(fā)新的飲料磺平。對于這些飲料而言魂仍,某些調(diào)料可能并不合適,但是子類仍然會繼承那些本就不合適的方法拣挪,例如我就想要一杯水擦酌,加奶泡(hasWhip)就不合適。
  • 第四菠劝,如果用戶需要雙倍的摩卡咖啡赊舶,又應(yīng)該怎么辦呢?

那么根據(jù)第四個問題赶诊,假如我們需要雙倍摩卡豆?jié){奶泡拿鐵咖啡時笼平,該如何去運算賬單呢?首先舔痪,我們先把前面的深度烘焙摩卡咖啡的設(shè)計圖放在這里寓调。


深度烘焙摩卡咖啡

然后我們只需要將Mocha的裝飾者加一,即可


雙倍摩卡豆?jié){奶泡拿鐵咖啡

實現(xiàn)星巴茲咖啡代碼

前面已經(jīng)把設(shè)計思想都設(shè)計出來了锄码,接下來是將其具體實現(xiàn)了夺英。首先從Beverage類下手

public abstract class Beverage1 {
    String description="Unknown Beverage";
    
    public String getDescription(){
        return description;
    }
    
    public abstract double cost();
}

Beverage類非常簡單,然后再實現(xiàn)Condiment(調(diào)料類)滋捶,該類為抽象類痛悯,也為裝飾者類

public abstract class CondimentDecorator extends Beverage1{

    //所有的調(diào)料裝飾者都必須重新實現(xiàn) getDescription()方法。 
    public abstract String getDescription();
}

前面已經(jīng)有了飲料的基類重窟,那么我們來實現(xiàn)一些具體的飲料類载萌。首先從濃縮咖啡(Espresso))開始,這里需要重寫cost()方法和getDescription()方法

public class Espresso extends Beverage1{
    
    public Espresso(){
        //為了要設(shè)置飲料的描述巡扇,我 們寫了一個構(gòu)造器炒考。記住, description實例變量繼承自Beverage1
        description="Espresso";
    }
    
    public double cost() {
        //最后霎迫,需要計算Espresso的價錢斋枢,現(xiàn)在不需要管調(diào)料的價錢,直接把Espresso的價格$1.99返回即可知给。
        return 1.99;
    }
}

再實現(xiàn)一個類似的飲料HouseBlend類瓤帚。

public class HouseBlend extends Beverage1{

    public HouseBlend(){
        description="HouseBlend";
    }
    
    public double cost() {
      
        return 0.89;
    }
}

重新設(shè)計DarkRoast1

public class DarkRoast1 extends Beverage1{
   
   public DarkRoast1(){
       description="DarkRoast1";
   }
   
   public double cost() {
     
       return 0.99;
   }

}

接下來就是調(diào)料的代碼描姚,我們一開始已經(jīng)實現(xiàn)了抽象組件類(Beverage),有了具體的組件(HouseBlend)戈次,也有了已經(jīng)完成抽象裝飾者(CondimentDecorator)⌒保現(xiàn)在只需要實現(xiàn)具體的裝飾者。首先我們先完成摩卡(Mocha)

public class Mocha extends CondimentDecorator{
    /**
     * 要讓Mocha能夠引用一個Beverage怯邪,采用以下做法
     * 1.用一個實例記錄飲料绊寻,也就是被裝飾者
     * 2.想辦法讓被裝飾者(飲料)被記錄在實例變量中。這里的做法是:
     * 把飲料當(dāng)作構(gòu)造器的參數(shù)悬秉,再由構(gòu)造器將此飲料記錄在實例變量中
     */
    Beverage1 beverage;
    
    public Mocha(Beverage1 beverage) {
        this.beverage=beverage;
    }
    
    public String getDescription() {
        //這里將調(diào)料也體現(xiàn)在相關(guān)參數(shù)中
        return beverage.getDescription()+",Mocha";
    }
    
    /**
     * 想要計算帶摩卡的飲料的價格澄步,需要調(diào)用委托給被裝飾者,以計算價格和泌,
     * 然后加上Mocha的價格村缸,得到最終的結(jié)果。
     */
    public double cost() {
        return 0.21+beverage.cost();
    }
    
    

}

還有奶泡(Whip)類

public class Whip extends CondimentDecorator{
    /**
     * 要讓W(xué)hip能夠引用一個Beverage武氓,采用以下做法
     * 1.用一個實例記錄飲料梯皿,也就是被裝飾者
     * 2.想辦法讓被裝飾者(飲料)被記錄在實例變量中。這里的做法是:
     * 把飲料當(dāng)作構(gòu)造器的參數(shù)县恕,再由構(gòu)造器將此飲料記錄在實例變量中
     */
    Beverage1 beverage;
    
    public Whip(Beverage1 beverage) {
        this.beverage=beverage;
    }
    
    public String getDescription() {
        //這里將調(diào)料也體現(xiàn)在相關(guān)參數(shù)中
        return beverage.getDescription()+",Whip";
    }
    
    /**
     * 想要計算帶奶泡的飲料的價格东羹,需要調(diào)用委托給被裝飾者,以計算價格忠烛,
     * 然后加上Whip的價格属提,得到最終的結(jié)果。
     */
    public double cost() {
        return 0.22+beverage.cost();
    }
}

豆?jié){Soy類

public class Soy extends CondimentDecorator{
    /**
     * 要讓Soy能夠引用一個Beverage况木,采用以下做法
     * 1.用一個實例記錄飲料,也就是被裝飾者
     * 2.想辦法讓被裝飾者(飲料)被記錄在實例變量中旬迹。這里的做法是:
     * 把飲料當(dāng)作構(gòu)造器的參數(shù)火惊,再由構(gòu)造器將此飲料記錄在實例變量中
     */
    Beverage1 beverage;
    
    public Soy(Beverage1 beverage) {
        this.beverage=beverage;
    }
    
    public String getDescription() {
        //這里將調(diào)料也體現(xiàn)在相關(guān)參數(shù)中
        return beverage.getDescription()+",Soy";
    }
    
    /**
     * 想要計算帶豆?jié){的飲料的價格,需要調(diào)用委托給被裝飾者奔垦,以計算價格屹耐,
     * 然后加上Soy的價格,得到最終的結(jié)果椿猎。
     */
    public double cost() {
        return 0.21+beverage.cost();
    }
}

接下來就是調(diào)用測試類惶岭,具體實現(xiàn)如下:

public class StarbuzzCoffe {
    
    public static void main(String[] args) {
        //訂購一杯Espresso,不需要調(diào)料犯眠,打印他的價格和描述
        Beverage1 beverage=new Espresso();
        System.out.println(beverage.getDescription()+"$"
                +beverage.cost());
        
        //開始裝飾雙倍摩卡+奶泡咖啡
        Beverage1 beverage2=new DarkRoast1();
        beverage2=new Mocha(beverage2);
        beverage2=new Mocha(beverage2);
        beverage2=new Whip(beverage2);
        
        System.out.println(beverage2.getDescription()+"$"
                +beverage2.cost());
        
        //
        Beverage1 beverage3=new HouseBlend();
        beverage3=new Soy(beverage3);
        beverage3=new Mocha(beverage3);
        beverage3=new Whip(beverage3);
        
        System.out.println(beverage3.getDescription()+"$"
                +beverage3.cost());
        
        
    }
}

運行結(jié)果:


運行結(jié)果

到這里雌团,我們已經(jīng)完成裝飾者模式對于星巴茲咖啡的改造篇裁。

5.Java中的真實裝飾者

前面已經(jīng)研究了裝飾者模式的原理和實現(xiàn)方式,那么在JAVA語言本身是否有裝飾者模式的使用范例呢,答案是肯定有的,那就是I/O流挡鞍。

第一次查閱I/O源碼,都會覺得類真多,而且一環(huán)嵌一環(huán),閱讀起來會非常麻煩艇挨。但是只要清楚I/O是根據(jù)裝飾者模式設(shè)計,就很容易理解韭赘。我們先來看一下一個范例:

讀取文件

分析一下,其中BufferedInputStream及LineNumberInputStream都擴展自
FilterInputStream缩滨,而FilterInputStream是一個抽象的裝飾類。這樣看有些抽象泉瞻,我們將其中的類按照裝飾者模式進行結(jié)構(gòu)化脉漏,方便理解。

java.io類

我們發(fā)現(xiàn)瓦灶,和星巴茲的設(shè)計相比鸠删,java.io其實并沒有多大的差異。但是從java.io流我們也會發(fā)現(xiàn)裝飾者模式一個非常嚴(yán)重的"缺點":使用裝飾者模式贼陶,常常會造成設(shè)計中有大量的小類刃泡,數(shù)量還非常多,這對于學(xué)習(xí)API的程序員來說就增加了學(xué)習(xí)難度和學(xué)習(xí)成本碉怔。但是烘贴,懂得裝飾者模式以后會非常容易理解和設(shè)計相關(guān)的類。

6.設(shè)計自己的IO類

在理解裝飾者模式和java.io的設(shè)計后撮胧,我們將磨煉下自己的熟悉程度桨踪,沒錯,就是自己設(shè)計一個Java I/O裝飾者芹啥,需求如下:

編寫一個裝飾者锻离,把輸入流內(nèi)的所有大寫字符轉(zhuǎn)成小寫。舉例:當(dāng)讀
取“ ASDFGHJKLQWERTYUIOPZXCVBNM”墓怀,裝飾者會將它轉(zhuǎn)成“ asdghjklqwertyuiopzxcvbnm”汽纠。具體的辦法在于擴展FilterInputStream類,并覆蓋read()方法就行了傀履。

public class LowerCaseInputStream extends FilterInputStream{
    
    public LowerCaseInputStream(InputStream inputStream){
        super(inputStream);
    }
    
    
    public int read() throws IOException {
       int c=super.read();
       //判斷相關(guān)的字符是否為大寫虱朵,并轉(zhuǎn)為小寫
       return (c==-1?c:Character.toLowerCase((char)c));
    }
    
    /**
     * 
     *針對字符數(shù)組進行大寫轉(zhuǎn)小寫操作
     * @see java.io.FilterInputStream#read(byte[], int, int)
     */
    public int read(byte[] b, int off, int len) throws IOException {
        int result=super.read(b,off,len);
        for(int i=off;i<off+result;i++){
            b[i]=(byte) Character.toLowerCase((char)b[i]);
        }
        return result;
    }

}

接下來我們構(gòu)建測試類InputTest

public class InputTest {
    public static void main(String[] args) {
        int c;
        try {
            InputStream inputStream=new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
            while((c=inputStream.read())>=0){
                System.out.print((char)c);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

其中test.txt的內(nèi)容可以自行編輯,放在項目根目錄下我的內(nèi)容原文為:


test.txt原文

運行結(jié)果為:

運行結(jié)果

7.總結(jié)

至此钓账,我們已經(jīng)掌握了裝飾者模式的相關(guān)知識點碴犬。總結(jié)一下:

第五設(shè)計原則
類應(yīng)該對拓展開放梆暮,對修改關(guān)閉服协。

裝飾者模式動態(tài)地將責(zé)任附加到對象上。
若要擴展功能啦粹,裝飾者提供了比繼承更有彈性
的替代方案蚯涮。

相應(yīng)的資料和代碼托管地址https://github.com/jixiang52002/HFDesignPattern

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末治专,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子遭顶,更是在濱河造成了極大的恐慌张峰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棒旗,死亡現(xiàn)場離奇詭異喘批,居然都是意外死亡,警方通過查閱死者的電腦和手機铣揉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門饶深,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逛拱,你說我怎么就攤上這事敌厘。” “怎么了朽合?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵俱两,是天一觀的道長。 經(jīng)常有香客問我曹步,道長宪彩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任讲婚,我火速辦了婚禮尿孔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筹麸。我一直安慰自己活合,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布物赶。 她就那樣靜靜地躺著白指,像睡著了一般。 火紅的嫁衣襯著肌膚如雪块差。 梳的紋絲不亂的頭發(fā)上侵续,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天倔丈,我揣著相機與錄音憨闰,去河邊找鬼。 笑死需五,一個胖子當(dāng)著我的面吹牛鹉动,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宏邮,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泽示,長吁一口氣:“原來是場噩夢啊……” “哼缸血!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起械筛,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤捎泻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后埋哟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笆豁,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年赤赊,在試婚紗的時候發(fā)現(xiàn)自己被綠了闯狱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡抛计,死狀恐怖哄孤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吹截,我是刑警寧澤瘦陈,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站饭弓,受9級特大地震影響双饥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弟断,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一咏花、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阀趴,春花似錦昏翰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至叔汁,卻和暖如春统求,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背据块。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工码邻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人另假。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓像屋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親边篮。 傳聞我的和親對象是個殘疾皇子己莺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

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