java設(shè)計(jì)模式-訪問(wèn)者模式

定義

訪問(wèn)者模式是對(duì)象的行為模式。訪問(wèn)者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作真友。一旦這些操作需要修改的話赡突,接收這個(gè)操作的數(shù)據(jù)結(jié)構(gòu)則可以保持不變。

分派的概念

變量被聲明時(shí)的類型叫做變量的靜態(tài)類型Static Type月而,有些人又把靜態(tài)類型叫做明顯類型Apparent Type;而變涼做引用的對(duì)象的真實(shí)類型又叫作變量的實(shí)際類型Actual Type议纯。比如:

List list = null;
list = new ArrayList();

聲明了一個(gè)變量list父款,它的靜態(tài)類型(也成為明顯類型)是List,而它的實(shí)際類型是ArrayList瞻凤。

根據(jù)對(duì)象的類型而對(duì)方法進(jìn)行的選擇憨攒,就是分派Dispatch,分派Dispatch有分為兩種:靜態(tài)分派動(dòng)態(tài)分派阀参。

靜態(tài)分派(Static Dispatch)發(fā)生在編譯時(shí)期肝集,分派根據(jù)靜態(tài)類型信息發(fā)生。靜態(tài)分派對(duì)于我們來(lái)說(shuō)并不陌生蛛壳,方法重載就是靜態(tài)分派杏瞻。

動(dòng)態(tài)分派(Dynamic Dispatch)發(fā)生在運(yùn)行期間,動(dòng)態(tài)分派動(dòng)態(tài)的置換掉某個(gè)方法衙荐。

靜態(tài)分派

Java通過(guò)方法重載支持靜態(tài)分派捞挥。用墨子騎馬的故事作為例子,墨子可以騎白馬或者黑馬忧吟。墨子與白馬砌函、黑馬和馬的類圖如下所示:

墨子騎馬類圖

馬的定義如下

public class Horse {
    public void eat() {
        System.out.println("馬吃草");
    }
}

白馬定義如下

public class WhiteHorse extends Horse {
    @Override
    public void eat() {
        System.out.println("白馬吃草");
    }
}

黑馬定義如下

public class BlackHorse extends Horse {
    @Override
    public void eat() {
        System.out.println("黑馬吃草");
    }
}

在這個(gè)系統(tǒng)中,墨子由Mozi類代表

public class MoZi {
    public void ride(Horse horse) {
        System.out.println("騎馬");
    }
    public void ride(WhiteHorse horse) {
        System.out.println("騎白馬");
    }
    public void ride(BlackHorse horse) {
        System.out.println("騎黑馬");
    }
    public static void main(String[] args) {
        Horse horse1 = new WhiteHorse();
        Horse horse2 = new BlackHorse();
        MoZi moZi = new MoZi();
        moZi.ride(horse1);
        moZi.ride(horse2);
    }
}

顯然,MoZi類的ride()方法是由三個(gè)方法重載而成的讹俊。這三個(gè)方法垦沉,分別接收的參數(shù)類型為馬Horse、白馬WhiteHorse劣像、黑馬BlockHorse乡话。

然而在實(shí)際運(yùn)行的時(shí)候,程序會(huì)打印出兩行相同的結(jié)果:“騎馬”耳奕。換言之绑青,墨子所騎的都是馬。

為什么呢屋群??jī)纱螌?duì)ride()方法的調(diào)用傳入的是不同的參數(shù)闸婴,也就是horse1horse2。它們雖然具有不同的真實(shí)類型芍躏,但是它們的靜態(tài)類型都是一樣的邪乍,均為Horse類型。

重載方法的分派是根據(jù)靜態(tài)類型進(jìn)行的对竣,這個(gè)分派過(guò)程在編譯時(shí)期就完成了庇楞。

動(dòng)態(tài)分派

我們關(guān)注到,在Horse類下定義了eat()方法否纬,WhiteHorseBlockHorse方法重寫了這個(gè)方法吕晌,由此,當(dāng)客戶端這樣調(diào)用時(shí)

public class Client {
    public static void main(String[] args) {
        Horse horse = new WhiteHorse();
        horse.eat();
    }
}

在這里临燃,變量horse的靜態(tài)類型是Horse睛驳,而真實(shí)類型是WhiteHorse。如果上邊代碼中的eat()方法調(diào)用的是WhiteHorse類的eat()方法膜廊,那么打印的結(jié)果就是“白馬吃草”乏沸;相反,如果上面的eat()方法調(diào)用的是Horse類的eat()方法爪瓜,那么打印的結(jié)果就是“馬吃草”蹬跃。

所以,問(wèn)題的核心就是Java編譯器在編譯時(shí)期并不總是知道哪些代碼會(huì)被執(zhí)行钥勋,因?yàn)榫幾g器僅僅知道對(duì)象的靜態(tài)類型炬转,而不知道對(duì)象的真實(shí)類型;而方法的調(diào)用則是根據(jù)對(duì)象的真實(shí)類型算灸,而不是靜態(tài)類型。這樣以來(lái)驻啤,上邊的eat()方法調(diào)用的是WhiteHorse類的eat()方法菲驴,打印的結(jié)果是“白馬吃草”;

分派的類型

一個(gè)方法所屬的對(duì)象叫做方法的接收者骑冗,方法的接收者與方法的參數(shù)統(tǒng)稱為方法的宗量赊瞬。比如下面的Test

public class Test {
    public void print(String str){
        System.out.println(str);
    }
}

在上面的類中先煎,print()方法屬于Test對(duì)象,所以它的接收者也就是Test對(duì)象了巧涧。print()方法有一個(gè)參數(shù)是str薯蝎,它的類型是String

根據(jù)分派可以基于多少種宗量谤绳,可以將面向?qū)ο蟮恼Z(yǔ)言劃分為單分派語(yǔ)言Uni-Dispatch和多分派語(yǔ)言Multi-Dispatch占锯。單分派語(yǔ)言可以根據(jù)一個(gè)宗量的類型進(jìn)行對(duì)方法的選擇,多分派語(yǔ)言根據(jù)多于一個(gè)的宗量的類型對(duì)方法進(jìn)行選擇缩筛。

C++和Java均是單分派語(yǔ)言消略,多分派語(yǔ)言的例子包括CLOS和Cecil。按照這樣的區(qū)分瞎抛,Java就是動(dòng)態(tài)的單分派語(yǔ)言艺演,因?yàn)檫@種語(yǔ)言的動(dòng)態(tài)分派僅僅會(huì)考慮到方法的接收者的類型,同時(shí)又是靜態(tài)的多分派語(yǔ)言桐臊,因?yàn)檫@種語(yǔ)言對(duì)于重載方法的分派會(huì)考慮到方法的接收者的類型以及方法的所有參數(shù)的類型胎撤。

在一個(gè)支持動(dòng)態(tài)單分派的語(yǔ)言里面,由兩個(gè)條件決定了一個(gè)請(qǐng)求會(huì)調(diào)用哪一個(gè)操作:一是請(qǐng)求的名字断凶,二是接收者的真實(shí)類型伤提。單分派限制了方法的選擇過(guò)程,使得只有一個(gè)宗量可以被考慮到懒浮,這個(gè)宗量通常就是方法的接收者飘弧。在Java語(yǔ)言里面,如果一個(gè)操作是作用于某個(gè)類型不明的對(duì)象上面砚著,那么對(duì)這個(gè)對(duì)象的真實(shí)類型測(cè)試僅會(huì)發(fā)生一次次伶,這就是動(dòng)態(tài)的單分派的特征。

雙重分派

一個(gè)方法根據(jù)兩個(gè)宗量的類型來(lái)決定執(zhí)行不同的代碼稽穆,這就是“雙重分派”冠王。Java語(yǔ)言不支持動(dòng)態(tài)的多分派,也就意味著Java不支持動(dòng)態(tài)的雙分派舌镶。但是通過(guò)使用設(shè)計(jì)模式柱彻,也可以在Java語(yǔ)言里面實(shí)現(xiàn)動(dòng)態(tài)的雙重分派。

在Java語(yǔ)言中可以通過(guò)兩次調(diào)用方法來(lái)達(dá)到兩次分派的目的餐胀。類圖如下所示:

Java中雙重分派的實(shí)現(xiàn)方式
Java中雙重分派的實(shí)現(xiàn)方式

在圖中有兩個(gè)對(duì)象哟楷,左邊的叫做West,右邊的叫做East》裨郑現(xiàn)在West對(duì)象首先調(diào)用East對(duì)象的goEast()方法卖擅,并將它自己傳入。在East對(duì)象被調(diào)用時(shí),立即根據(jù)傳入的參數(shù)知道了調(diào)用者是誰(shuí)惩阶,于是反過(guò)來(lái)調(diào)用“調(diào)用者”對(duì)象的getWest()方法挎狸。通過(guò)兩次調(diào)用將程序控制權(quán)輪番交給兩個(gè)對(duì)象,其時(shí)序圖如下所示:

Java中雙重分派的實(shí)現(xiàn)時(shí)序圖

這樣就出現(xiàn)了兩次方法調(diào)用断楷,程序控制權(quán)被兩個(gè)對(duì)象像傳球一樣锨匆,首先由West對(duì)象傳給了East對(duì)象,然后又被返傳給了West對(duì)象冬筒。

但是僅僅返傳了一下球恐锣,并不能解決雙重分派的問(wèn)題。關(guān)鍵是怎么利用這兩次調(diào)用账千,以及Java語(yǔ)言的動(dòng)態(tài)單分派功能侥蒙,使得在這種傳球的過(guò)程中,能夠出發(fā)兩次單分派匀奏。

動(dòng)態(tài)單分派在Java語(yǔ)言中是在子類重寫父類的方法時(shí)發(fā)生的鞭衩。換言之,WestEast都必須分別置身于自己的類型等級(jí)結(jié)構(gòu)中娃善,如下圖所示:

示例代碼

West

public abstract class West {
    public abstract void goWest1(SubEast1 east);
    public abstract void goWest2(SubEast2 east);
}

SubWest1

public class SubWest1 extends West {
    @Override
    public void goWest1(SubEast1 east) {
        System.out.println("SubWest1 + " + east.myName1());
    }

    @Override
    public void goWest2(SubEast2 east) {
        System.out.println("SubWest1 + " + east.myName2());
    }
}

SubWest2

public class SubWest2 extends West {
    @Override
    public void goWest1(SubEast1 east) {
        System.out.println("SubWest2 + " + east.myName1());
    }

    @Override
    public void goWest2(SubEast2 east) {
        System.out.println("SubWest2 + " + east.myName2());
    }
}

East

public abstract class East {
    public abstract void goEast(West west);
}

SubEast1

public class SubEast1 extends East {
    @Override
    public void goEast(West west) {
        west.goWest1(this);
    }

    public String myName1() {
        return "SubEast1";
    }
}

SubEast2

public class SubEast2 extends East {
    @Override
    public void goEast(West west) {
        west.goWest2(this);
    }
    public String myName2() {
        return "SubEast2";
    }
}

客戶端類

public class Client {
    public static void main(String[] args) {
        East east = new SubEast1();
        West west = new SubWest1();
        east.goEast(west);

        //組合2
        east = new SubEast1();
        west = new SubWest2();
        east.goEast(west);
    }
}

執(zhí)行結(jié)果如下

SubWest1 + SubEast1
SubWest2 + SubEast1

系統(tǒng)運(yùn)行時(shí)论衍,會(huì)首先創(chuàng)建SubWest1SubEast1對(duì)象,然后客戶端調(diào)用SubEast1goEast()方法聚磺,并將SubWest1對(duì)象傳入坯台。由于SubEast1對(duì)象重寫了其超類East的goEast()方法,因此瘫寝,這個(gè)時(shí)候就發(fā)生了一次動(dòng)態(tài)的單分派蜒蕾。當(dāng)SubEast1對(duì)象接到調(diào)用時(shí),會(huì)從參數(shù)中得到SubWest1對(duì)象焕阿,所以它就立即調(diào)用這個(gè)對(duì)象的goWest1方法咪啡,并將自己傳入。由于SubEast1對(duì)象有權(quán)選擇調(diào)用哪一個(gè)對(duì)象暮屡,因此撤摸,在此時(shí)又進(jìn)行一次動(dòng)態(tài)的方法分派。

這個(gè)時(shí)候SubWest1對(duì)象就得到SubEast1對(duì)象褒纲。通過(guò)調(diào)用這個(gè)對(duì)象的myName1()方法准夷,就可以打印出自己的名字和SubEast對(duì)象的名字,其時(shí)序圖如下所示:

調(diào)用時(shí)序圖

由于這兩個(gè)名字一個(gè)來(lái)自East等級(jí)結(jié)構(gòu)莺掠。另一個(gè)來(lái)自West等級(jí)結(jié)構(gòu)中衫嵌。因此魏保,它們的組合是動(dòng)態(tài)決定的召锈。這就是動(dòng)態(tài)雙重分派的實(shí)現(xiàn)機(jī)制。

訪問(wèn)者模式的結(jié)構(gòu)

訪問(wèn)者模式適用于數(shù)據(jù)結(jié)構(gòu)相對(duì)穩(wěn)定的系統(tǒng)计贰,它把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作之間的耦合解脫開(kāi)掖棉,使得操作集合可以相對(duì)自由的演化墓律。訪問(wèn)者模式的簡(jiǎn)略圖如下所示:

數(shù)據(jù)結(jié)構(gòu)的每一個(gè)節(jié)點(diǎn)都可以接受一個(gè)訪問(wèn)者的調(diào)用,此節(jié)點(diǎn)向訪問(wèn)者對(duì)象傳入節(jié)點(diǎn)對(duì)象幔亥,而訪問(wèn)者對(duì)象則反過(guò)來(lái)執(zhí)行節(jié)點(diǎn)對(duì)象的操作耻讽。這樣的過(guò)程叫做“雙重分派”。節(jié)點(diǎn)調(diào)用訪問(wèn)者帕棉,將它自己傳入针肥,訪問(wèn)者將某算法針對(duì)此節(jié)點(diǎn)執(zhí)行。訪問(wèn)者模式的示意性類圖如下所示:

訪問(wèn)者模式的示意性類圖

訪問(wèn)者模式涉及到的角色如下:

  • 抽象訪問(wèn)者角色(Visitor):聲明了一個(gè)或者多個(gè)方法操作香伴,行程所有的具體訪問(wèn)者角色必須實(shí)現(xiàn)的接口慰枕。
  • 具體訪問(wèn)者角色(ConcreteVisitor):實(shí)現(xiàn)抽象訪問(wèn)者所聲明的接口,也就是抽象訪問(wèn)者所聲明的各個(gè)訪問(wèn)操作即纲。
  • 抽象節(jié)點(diǎn)角色(Node):聲明一個(gè)接受操作具帮,接受一個(gè)訪問(wèn)者對(duì)象作為一個(gè)參數(shù)。
  • 具體節(jié)點(diǎn)角色(ConcreteNode):實(shí)現(xiàn)了抽象節(jié)點(diǎn)所規(guī)定的接受操作低斋。
  • 結(jié)構(gòu)對(duì)象角色(ObjectStructure):有如下的責(zé)任:可以遍歷結(jié)構(gòu)中的所有元素蜂厅;如果需要,提供一個(gè)高層次的接口讓訪問(wèn)者對(duì)象可以訪問(wèn)每一個(gè)元素膊畴;如果需要掘猿,可以設(shè)計(jì)成一個(gè)復(fù)合對(duì)象或者一個(gè)聚集,如ListSet唇跨。

示例代碼

可以看出稠通,抽象訪問(wèn)者角色為每一個(gè)具體節(jié)點(diǎn)都準(zhǔn)備了一個(gè)訪問(wèn)操作。由于有兩個(gè)節(jié)點(diǎn)买猖,因此改橘,對(duì)應(yīng)就有兩個(gè)訪問(wèn)操作。

public interface Visitor {
    /**
     * 對(duì)于NodeA的訪問(wèn)操作
     * @param nodeA
     */
    public void visit(NodeA nodeA);

    /**
     * 對(duì)于NodeB的訪問(wèn)操作
     * @param nodeB
     */
    public void visit(NodeB nodeB);
}

具體訪問(wèn)者VisitorA

public class VisitorA implements Visitor {
    @Override
    public void visit(NodeA nodeA) {
        System.out.println("VisitorA + " + nodeA.operationA());
    }

    @Override
    public void visit(NodeB nodeB) {
        System.out.println("VisitorA + " + nodeB.operationB());
    }
}

具體訪問(wèn)者VisitorB

public class VisitorB implements Visitor {
    @Override
    public void visit(NodeA nodeA) {
        System.out.println("VisitorB + " + nodeA.operationA());
    }

    @Override
    public void visit(NodeB nodeB) {
        System.out.println("VisitorB + " + nodeB.operationB());
    }
}

抽象節(jié)點(diǎn)類

public abstract class Node {
    /**
     * 接受操作
     * @param visitor
     */
    public abstract void accept(Visitor visitor);
}

具體節(jié)點(diǎn)類NodeA

public class NodeA extends Node {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    /**
     * NodeA特有的操作
     * @return
     */
    public String operationA() {
        return "NodeA";
    }
}

具體節(jié)點(diǎn)類NodeB

public class NodeB extends Node {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    /**
     * NodeB特有的操作
     * @return
     */
    public String operationB() {
        return "NodeB";
    }
}

結(jié)構(gòu)對(duì)象角色類政勃,這個(gè)結(jié)構(gòu)對(duì)象持有一個(gè)聚集唧龄,并向外界提供add()方法作為對(duì)聚集的管理操作。通過(guò)調(diào)用這個(gè)方法奸远,可以動(dòng)態(tài)的增加一個(gè)新的節(jié)點(diǎn)既棺。

public class ObjectStructure {
    private List<Node> nodes = new ArrayList<>();

    /**
     * 執(zhí)行方法操作
     * @param visitor
     */
    public void action(Visitor visitor) {
        for (Node node :
                nodes) {
            node.accept(visitor);
        }
    }

    /**
     * 添加一個(gè)新元素
     * @param node
     */
    public void add(Node node) {
        nodes.add(node);
    }
}

客戶端類

public class Client {
    public static void main(String[] args) {
        //創(chuàng)建一個(gè)結(jié)構(gòu)對(duì)象
        ObjectStructure objectStructure = new ObjectStructure();
        //給結(jié)構(gòu)增加節(jié)點(diǎn)
        objectStructure.add(new NodeA());
        objectStructure.add(new NodeB());
        //創(chuàng)建一個(gè)訪問(wèn)者
        Visitor visitor = new VisitorA();
        objectStructure.action(visitor);
    }
}

雖然在這個(gè)示意性的實(shí)現(xiàn)里并沒(méi)有出現(xiàn)一個(gè)復(fù)雜的具有多個(gè)樹(shù)枝節(jié)點(diǎn)的對(duì)象樹(shù)結(jié)構(gòu),但是懒叛,在實(shí)際系統(tǒng)中訪問(wèn)者模式通常是用來(lái)處理復(fù)雜的對(duì)象樹(shù)結(jié)構(gòu)的丸冕,而且訪問(wèn)者模式可以用來(lái)處理跨多個(gè)等級(jí)結(jié)構(gòu)的樹(shù)結(jié)構(gòu)問(wèn)題。這正是訪問(wèn)者模式的功能強(qiáng)大之處薛窥。

準(zhǔn)備過(guò)程時(shí)序圖

首先胖烛,這個(gè)示意性的客戶端創(chuàng)建了一個(gè)結(jié)構(gòu)對(duì)象眼姐,然后將一個(gè)新的NodeA對(duì)象和一個(gè)新的NodeB對(duì)象傳入。

其次佩番,客戶端創(chuàng)建了一個(gè)VisitorA對(duì)象众旗,并將此對(duì)象傳給結(jié)構(gòu)對(duì)象。

然后趟畏,客戶端調(diào)用結(jié)構(gòu)對(duì)象聚集管理方法贡歧,將NodeANodeB節(jié)點(diǎn)加入到結(jié)構(gòu)對(duì)象中去。

最后赋秀,客戶端調(diào)用結(jié)構(gòu)對(duì)象的行為方法action()方法利朵,啟動(dòng)訪問(wèn)過(guò)程。

準(zhǔn)備過(guò)程時(shí)序圖

訪問(wèn)過(guò)程時(shí)序圖

訪問(wèn)過(guò)程時(shí)序圖

結(jié)構(gòu)對(duì)象會(huì)遍歷它自己所保存的聚集中的所有節(jié)點(diǎn)猎莲,在本系統(tǒng)中就是節(jié)點(diǎn)NodeANodeB绍弟。首先NodeA會(huì)被訪問(wèn)到,這個(gè)訪問(wèn)是由一下的操作組成的:

  1. NodeA對(duì)象的接受方法accept()被調(diào)用著洼,并將VisitorA對(duì)象本身傳入樟遣;
  2. NodeA對(duì)象反過(guò)來(lái)調(diào)用VisitorA對(duì)象的訪問(wèn)方法,并將NodeA對(duì)象本身傳入郭脂;
  3. VisitorA對(duì)象調(diào)用NodeA對(duì)象的特有方法operationA()年碘。

從而就完成了雙重分派過(guò)程,接著展鸡,NodeB會(huì)被訪問(wèn)屿衅,這個(gè)訪問(wèn)的過(guò)程跟NodeA被訪問(wèn)的過(guò)程是一樣的。

訪問(wèn)者模式的優(yōu)點(diǎn)

  • 好的擴(kuò)展性
    能夠在不修改對(duì)象結(jié)構(gòu)中的元素的情況下莹弊,為對(duì)象結(jié)構(gòu)中的元素添加新的功能涤久。
  • 好的復(fù)用性
    可以通過(guò)訪問(wèn)者定義整個(gè)結(jié)果對(duì)象通用的功能,從而提高復(fù)用程度忍弛。
  • 分離無(wú)關(guān)行為
    可以通過(guò)訪問(wèn)者來(lái)分離無(wú)關(guān)的行為响迂,把相關(guān)的行為封裝在一起,構(gòu)成一個(gè)訪問(wèn)者细疚,這樣沒(méi)個(gè)訪問(wèn)者的功能都比較單一蔗彤。

訪問(wèn)者模式的缺點(diǎn)

  • 對(duì)象結(jié)構(gòu)變化很困難
    不適用于對(duì)象結(jié)構(gòu)中的類經(jīng)常變化的情況,因?yàn)閷?duì)象結(jié)構(gòu)發(fā)生了改變疯兼,訪問(wèn)者的接口和訪問(wèn)者的實(shí)現(xiàn)都要發(fā)生相應(yīng)的改變然遏,代價(jià)太高。
  • 破壞封裝
    訪問(wèn)者模式通常需要對(duì)象結(jié)構(gòu)開(kāi)放內(nèi)部數(shù)據(jù)給訪問(wèn)者和ObjectStructure吧彪,這破壞了對(duì)象的封裝性

參考

《JAVA與模式》之訪問(wèn)者模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末待侵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姨裸,更是在濱河造成了極大的恐慌秧倾,老刑警劉巖怨酝,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異那先,居然都是意外死亡农猬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門胃榕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)盛险,“玉大人,你說(shuō)我怎么就攤上這事勋又。” “怎么了换帜?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵楔壤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我惯驼,道長(zhǎng)蹲嚣,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任祟牲,我火速辦了婚禮隙畜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘说贝。我一直安慰自己议惰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布乡恕。 她就那樣靜靜地躺著言询,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傲宜。 梳的紋絲不亂的頭發(fā)上运杭,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音函卒,去河邊找鬼辆憔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛报嵌,可吹牛的內(nèi)容都是我干的虱咧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼沪蓬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼彤钟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起跷叉,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逸雹,失蹤者是張志新(化名)和其女友劉穎营搅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梆砸,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡转质,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了帖世。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片休蟹。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖日矫,靈堂內(nèi)的尸體忽然破棺而出赂弓,到底是詐尸還是另有隱情,我是刑警寧澤哪轿,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布盈魁,位于F島的核電站,受9級(jí)特大地震影響窃诉,放射性物質(zhì)發(fā)生泄漏杨耙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一飘痛、第九天 我趴在偏房一處隱蔽的房頂上張望珊膜。 院中可真熱鬧,春花似錦宣脉、人聲如沸车柠。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)堪遂。三九已至,卻和暖如春萌庆,著一層夾襖步出監(jiān)牢的瞬間溶褪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工践险, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猿妈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓巍虫,卻偏偏與公主長(zhǎng)得像彭则,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子占遥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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