閱讀《重學(xué)設(shè)計模式》筆記8 - 責(zé)任鏈模式

一亿驾、前言

場地和場景的重要性

射擊??需要去靶場學(xué)習(xí)黄娘、滑雪??需要去雪場體驗糯而、開車??需要能上路實踐,而編程開發(fā)除了能完成產(chǎn)品的功能流程泊窘,還需要保證系統(tǒng)的可靠性能熄驼。就像你能聽到的一些系統(tǒng)監(jiān)控指標(biāo);QPS烘豹、TPS瓜贾、TP99TP999携悯、可用率祭芦、響應(yīng)時長等等,而這些指標(biāo)的總和評估就是一個系統(tǒng)的健康度憔鬼。但如果你幾乎沒有聽到這樣的技術(shù)術(shù)語龟劲,也沒接觸過類似高并發(fā)場景,那么就很像駕駛證的科目1考了100分轴或,但不能上路昌跌。沒有這樣的技術(shù)場景給你訓(xùn)練,讓你不斷的體會系統(tǒng)的脾氣秉性照雁,即便你有再多的想法都沒法實現(xiàn)蚕愤。所以,如果真的想學(xué)習(xí)一定要去一個有實操的場景饺蚊,下水試試才能學(xué)會狗刨萍诱。

二、開發(fā)環(huán)境

  1. JDK 1.8
  2. Idea + Maven

三污呼、責(zé)任鏈模式介紹

責(zé)任鏈模式

擊鼓傳雷裕坊,看上圖你是否想起周星馳有一個電影,大家坐在海邊圍成一個圈曙求,拿著一個點燃的炸彈碍庵,互相傳遞。

責(zé)任鏈模式的核心是解決一組服務(wù)中的先后執(zhí)行處理關(guān)系?悟狱,就有點像你沒錢花了静浴,需要家庭財務(wù)支出審批,10塊錢以下找閨女審批挤渐,100塊錢先閨女審批在媳婦審批苹享。你可以理解想象成當(dāng)你要跳槽的時候被安排的明明白白的被各個領(lǐng)導(dǎo)簽字放行。

四、案例場景模擬

618大促場景上線審批場景

在本案例中我們模擬在618大促期間的業(yè)務(wù)系統(tǒng)上線審批流程場景

像是這些一線電商類的互聯(lián)網(wǎng)公司得问,阿里囤攀、京東、拼多多等宫纬,在618期間都會做一些運(yùn)營活動場景以及提供的擴(kuò)容備戰(zhàn)焚挠,就像過年期間百度的紅包一樣。但是所有開發(fā)的這些系統(tǒng)都需要陸續(xù)的上線漓骚,因為臨近618有時候也有一些緊急的調(diào)整的需要上線蝌衔,但為了保障線上系統(tǒng)的穩(wěn)定性是盡可能的減少上線的,也會相應(yīng)的增強(qiáng)審批力度蝌蹂。就像一級響應(yīng)噩斟、二級響應(yīng)一樣。

而這審批的過程在隨著特定時間點會增加不同級別的負(fù)責(zé)人加入孤个,每個人就像責(zé)任鏈模式中的每一個核心點剃允。對于研發(fā)小伙伴并不需要關(guān)心具體的審批流程處理細(xì)節(jié),只需要知道這個上線更嚴(yán)格齐鲤,級別也更高斥废,但對于研發(fā)人員來說同樣是點擊相同的提審按鈕,等待審核给郊。

接下來我們就模擬這樣一個業(yè)務(wù)訴求場景营袜,使用責(zé)任鏈的設(shè)計模式來實現(xiàn)此功能。

1. 場景模擬工程

└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── AuthService.java
  • 這里的代碼結(jié)構(gòu)比較簡單丑罪,只有一個模擬審核和查詢審核結(jié)果的服務(wù)類荚板。相當(dāng)于你可以調(diào)用這個類去審核工程和獲取審核結(jié)構(gòu),這部分結(jié)果信息是模擬的寫到緩存實現(xiàn)吩屹。

2. 場景簡述

2.1 模擬審核服務(wù)

public class AuthService {

    private static Map<String, Date> authMap = new ConcurrentHashMap<String, Date>();

    public static Date queryAuthInfo(String uId, String orderId) {
        return authMap.get(uId.concat(orderId));
    }

    public static void auth(String uId, String orderId) {
        authMap.put(uId.concat(orderId), new Date());
    }

}
  • 這里面提供了兩個接口一個是查詢審核結(jié)果(queryAuthInfo)跪另、另外一個是處理審核(auth)。
  • 這部分是把由誰審核的和審核的單子ID作為唯一key值記錄到內(nèi)存Map結(jié)構(gòu)中煤搜。

五免绿、用一坨坨代碼實現(xiàn)

這里我們先使用最直接的方式來實現(xiàn)功能

按照我們的需求審批流程,平常系統(tǒng)上線只需要三級負(fù)責(zé)人審批就可以擦盾,但是到了618大促時間點嘲驾,就需要由二級負(fù)責(zé)以及一級負(fù)責(zé)人一起加入審批系統(tǒng)上線流程。在這里我們使用非常直接的if判斷方式來實現(xiàn)這樣的需求迹卢。

1. 工程結(jié)構(gòu)

└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── AuthController.java
  • 這部分非常簡單的只包含了一個審核的控制類辽故,就像有些伙伴開始寫代碼一樣,一個類寫所有需求腐碱。

2. 代碼實現(xiàn)

public class AuthController {

    private SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 時間格式化

    public AuthInfo doAuth(String uId, String orderId, Date authDate) throws ParseException {

        // 三級審批
        Date date = AuthService.queryAuthInfo("1000013", orderId);
        if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待三級審批負(fù)責(zé)人 ", "王工");

        // 二級審批
        if (authDate.after(f.parse("2020-06-01 00:00:00")) && authDate.before(f.parse("2020-06-25 23:59:59"))) {
            date = AuthService.queryAuthInfo("1000012", orderId);
            if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待二級審批負(fù)責(zé)人 ", "張經(jīng)理");
        }

        // 一級審批
        if (authDate.after(f.parse("2020-06-11 00:00:00")) && authDate.before(f.parse("2020-06-20 23:59:59"))) {
            date = AuthService.queryAuthInfo("1000011", orderId);
            if (null == date) return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待一級審批負(fù)責(zé)人 ", "段總");
        }

        return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):審批完成");
    }

}
  • 這里從上到下分別判斷了在指定時間范圍內(nèi)由不同的人員進(jìn)行審批誊垢,就像618上線的時候需要三個負(fù)責(zé)人都審批才能讓系統(tǒng)進(jìn)行上線。
  • 像是這樣的功能看起來很簡單的,但是實際的業(yè)務(wù)中會有很多部門喂走,但如果這樣實現(xiàn)就很難進(jìn)行擴(kuò)展殃饿,并且在改動擴(kuò)展調(diào)整也非常麻煩。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_AuthController() throws ParseException {
    AuthController authController = new AuthController();  

    // 模擬三級負(fù)責(zé)人審批
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authController.doAuth("49848144", "1000998004813441", new Date())));
    logger.info("測試結(jié)果:{}", "模擬三級負(fù)責(zé)人審批芋肠,王工");
    AuthService.auth("1000013", "1000998004813441");  

    // 模擬二級負(fù)責(zé)人審批                                 
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authController.doAuth("49848144", "1000998004813441", new Date())));
    logger.info("測試結(jié)果:{}", "模擬二級負(fù)責(zé)人審批乎芳,張經(jīng)理");
    AuthService.auth("1000012", "1000998004813441");    

    // 模擬一級負(fù)責(zé)人審批
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authController.doAuth("49848144", "1000998004813441", new Date())));
    logger.info("測試結(jié)果:{}", "模擬一級負(fù)責(zé)人審批,段總");
    AuthService.auth("1000011", "1000998004813441");            

    logger.info("測試結(jié)果:{}", "審批完成");
}
  • 這里模擬每次查詢是否審批完成帖池,隨著審批的不同節(jié)點秒咐,之后繼續(xù)由不同的負(fù)責(zé)人進(jìn)行審批操作。
  • authController.doAuth碘裕,是查看審批的流程節(jié)點、AuthService.auth攒钳,是審批方法用于操作節(jié)點流程狀態(tài)帮孔。

3.2 測試結(jié)果

23:25:00.363 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待三級審批負(fù)責(zé)人 王工"}
23:25:00.366 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬三級負(fù)責(zé)人審批,王工
23:25:00.367 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待二級審批負(fù)責(zé)人 張經(jīng)理"}
23:25:00.367 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬二級負(fù)責(zé)人審批不撑,張經(jīng)理
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待一級審批負(fù)責(zé)人 段總"}
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬一級負(fù)責(zé)人審批文兢,段總
23:25:00.368 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:審批完成

Process finished with exit code 0
  • 從測試結(jié)果上可以看到一層層的由不同的人員進(jìn)行審批,審批完成后到下一個人進(jìn)行處理焕檬。單看結(jié)果是滿足我們的訴求姆坚,只不過很難擴(kuò)展和調(diào)整流程,相當(dāng)于代碼寫的死死的实愚。

六兼呵、責(zé)任鏈模式重構(gòu)代碼

接下來使用裝飾器模式來進(jìn)行代碼優(yōu)化,也算是一次很小的重構(gòu)腊敲。

責(zé)任鏈模式可以讓各個服務(wù)模塊更加清晰击喂,而每一個模塊間可以通過next的方式進(jìn)行獲取。而每一個next是由繼承的統(tǒng)一抽象類實現(xiàn)的碰辅。最終所有類的職責(zé)可以動態(tài)的進(jìn)行編排使用懂昂,編排的過程可以做成可配置化。

1. 工程結(jié)構(gòu)

└── src
    └── main
        └── java
            └── org.itstack.demo.design
                ├── impl
                │    ├── Level1AuthLink.java
                │    ├── Level2AuthLink.java
                │    └── Level3AuthLink.java
                ├── AuthInfo.java
                └── AuthLink.java

責(zé)任鏈類圖

責(zé)任鏈類圖

責(zé)任鏈模式模型結(jié)構(gòu)

責(zé)任鏈模式模型結(jié)構(gòu)

  • 上圖是這個業(yè)務(wù)模型中責(zé)任鏈結(jié)構(gòu)的核心部分没宾,通過三個實現(xiàn)了統(tǒng)一抽象類AuthLink的不同規(guī)則凌彬,再進(jìn)行責(zé)任編排模擬出一條鏈路。這個鏈路就是業(yè)務(wù)中的責(zé)任鏈循衰。
  • 一般在使用責(zé)任鏈時候如果是場景比較固定铲敛,可以通過寫死到代碼中進(jìn)行初始化。但如果業(yè)務(wù)場景經(jīng)常變化可以做成xml配置的方式進(jìn)行處理会钝,也可以落到庫里進(jìn)行初始化操作原探。

2. 代碼實現(xiàn)

2.1 責(zé)任鏈中返回對象定義

public class AuthInfo {

    private String code;
    private String info = "";

    public AuthInfo(String code, String ...infos) {
        this.code = code;
        for (String str:infos){
            this.info = this.info.concat(str);
        }
    }
    
    // ...get/set
}
  • 這個類的是包裝了責(zé)任鏈處理過程中返回結(jié)果的類,方面處理每個責(zé)任鏈的返回信息。

2.2 鏈路抽象類定義

public abstract class AuthLink {

    protected Logger logger = LoggerFactory.getLogger(AuthLink.class);

    protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 時間格式化
    protected String levelUserId;                           // 級別人員ID
    protected String levelUserName;                         // 級別人員姓名
    private AuthLink next;                                  // 責(zé)任鏈

    public AuthLink(String levelUserId, String levelUserName) {
        this.levelUserId = levelUserId;
        this.levelUserName = levelUserName;
    }

    public AuthLink next() {
        return next;
    }

    public AuthLink appendNext(AuthLink next) {
        this.next = next;
        return this;
    }

    public abstract AuthInfo doAuth(String uId, String orderId, Date authDate);

}
  • 這部分是責(zé)任鏈咽弦,鏈接起來的核心部分徒蟆。AuthLink next,重點在于可以通過next方式獲取下一個鏈路需要處理的節(jié)點型型。
  • levelUserId段审、levelUserName,是責(zé)任鏈中的公用信息闹蒜,標(biāo)記每一個審核節(jié)點的人員信息寺枉。
  • 抽象類中定義了一個抽象方法,abstract AuthInfo doAuth绷落,這是每一個實現(xiàn)者必須實現(xiàn)的類姥闪,不同的審核級別處理不同的業(yè)務(wù)。

2.3 三個審核實現(xiàn)類

Level1AuthLink

public class Level1AuthLink extends AuthLink {

    public Level1AuthLink(String levelUserId, String levelUserName) {
        super(levelUserId, levelUserName);
    }

    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
        if (null == date) {
            return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待一級審批負(fù)責(zé)人 ", levelUserName);
        }
        AuthLink next = super.next();
        if (null == next) {
            return new AuthInfo("0000", "單號:", orderId, " 狀態(tài):一級審批完成負(fù)責(zé)人", " 時間:", f.format(date), " 審批人:", levelUserName);
        }

        return next.doAuth(uId, orderId, authDate);
    }

}

Level2AuthLink

public class Level2AuthLink extends AuthLink {

    private Date beginDate = f.parse("2020-06-11 00:00:00");
    private Date endDate = f.parse("2020-06-20 23:59:59");

    public Level2AuthLink(String levelUserId, String levelUserName) throws ParseException {
        super(levelUserId, levelUserName);
    }

    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
        if (null == date) {
            return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待二級審批負(fù)責(zé)人 ", levelUserName);
        }
        AuthLink next = super.next();
        if (null == next) {
            return new AuthInfo("0000", "單號:", orderId, " 狀態(tài):二級審批完成負(fù)責(zé)人", " 時間:", f.format(date), " 審批人:", levelUserName);
        }

        if (authDate.before(beginDate) || authDate.after(endDate)) {
            return new AuthInfo("0000", "單號:", orderId, " 狀態(tài):二級審批完成負(fù)責(zé)人", " 時間:", f.format(date), " 審批人:", levelUserName);
        }

        return next.doAuth(uId, orderId, authDate);
    }

}

Level3AuthLink

public class Level3AuthLink extends AuthLink {

    private Date beginDate = f.parse("2020-06-01 00:00:00");
    private Date endDate = f.parse("2020-06-25 23:59:59");

    public Level3AuthLink(String levelUserId, String levelUserName) throws ParseException {
        super(levelUserId, levelUserName);
    }

    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
        if (null == date) {
            return new AuthInfo("0001", "單號:", orderId, " 狀態(tài):待三級審批負(fù)責(zé)人 ", levelUserName);
        }
        AuthLink next = super.next();
        if (null == next) {
            return new AuthInfo("0000", "單號:", orderId, " 狀態(tài):三級審批負(fù)責(zé)人完成", " 時間:", f.format(date), " 審批人:", levelUserName);
        }

        if (authDate.before(beginDate) || authDate.after(endDate)) {
            return new AuthInfo("0000", "單號:", orderId, " 狀態(tài):三級審批負(fù)責(zé)人完成", " 時間:", f.format(date), " 審批人:", levelUserName);
        }

        return next.doAuth(uId, orderId, authDate);
    }

}
  • 如上三個類砌烁;Level1AuthLink筐喳、Level2AuthLinkLevel3AuthLink函喉,實現(xiàn)了不同的審核級別處理的簡單邏輯避归。
  • 例如第一個審核類中會先判斷是否審核通過,如果沒有審核通過則返回結(jié)果給調(diào)用方管呵,引導(dǎo)去審核梳毙。(這里簡單模擬審核后有時間信息不為空,作為判斷條件)
  • 判斷完成后獲取下一個審核節(jié)點捐下;super.next();账锹,如果不存在下一個節(jié)點,則直接返回結(jié)果坷襟。
  • 之后是根據(jù)不同的業(yè)務(wù)時間段進(jìn)行判斷是否需要牌废,二級和一級的審核。
  • 最后返回下一個審核結(jié)果啤握;next.doAuth(uId, orderId, authDate);鸟缕,有點像遞歸調(diào)用。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_AuthLink() throws ParseException {
    AuthLink authLink = new Level3AuthLink("1000013", "王工")
            .appendNext(new Level2AuthLink("1000012", "張經(jīng)理")
                    .appendNext(new Level1AuthLink("1000011", "段總")));

    logger.info("測試結(jié)果:{}", JSON.toJSONString(authLink.doAuth("49848144", "1000998004813441", new Date())));

    // 模擬三級負(fù)責(zé)人審批
    AuthService.auth("1000013", "1000998004813441");
    logger.info("測試結(jié)果:{}", "模擬三級負(fù)責(zé)人審批排抬,王工");
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authLink.doAuth("49848144", "1000998004813441", new Date())));

    // 模擬二級負(fù)責(zé)人審批
    AuthService.auth("1000012", "1000998004813441");
    logger.info("測試結(jié)果:{}", "模擬二級負(fù)責(zé)人審批懂从,張經(jīng)理");
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authLink.doAuth("49848144", "1000998004813441", new Date())));

    // 模擬一級負(fù)責(zé)人審批
    AuthService.auth("1000011", "1000998004813441");
    logger.info("測試結(jié)果:{}", "模擬一級負(fù)責(zé)人審批,段總");
    logger.info("測試結(jié)果:{}", JSON.toJSONString(authLink.doAuth("49848144", "1000998004813441", new Date())));
}
  • 這里包括最核心的責(zé)任鏈創(chuàng)建蹲蒲,實際的業(yè)務(wù)中會包裝到控制層番甩;AuthLink authLink = new Level3AuthLink("1000013", "王工") .appendNext(new Level2AuthLink("1000012", "張經(jīng)理") .appendNext(new Level1AuthLink("1000011", "段總"))); 通過把不同的責(zé)任節(jié)點進(jìn)行組裝,構(gòu)成一條完整業(yè)務(wù)的責(zé)任鏈届搁。
  • 接下里不斷的執(zhí)行查看審核鏈路authLink.doAuth(...)缘薛,通過返回結(jié)果對數(shù)據(jù)進(jìn)行3窍育、2、1級負(fù)責(zé)人審核宴胧,直至最后審核全部完成漱抓。

3.2 測試結(jié)果

23:49:46.585 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待三級審批負(fù)責(zé)人 王工"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬三級負(fù)責(zé)人審批,王工
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待二級審批負(fù)責(zé)人 張經(jīng)理"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬二級負(fù)責(zé)人審批恕齐,張經(jīng)理
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0001","info":"單號:1000998004813441 狀態(tài):待一級審批負(fù)責(zé)人 段總"}
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:模擬一級負(fù)責(zé)人審批乞娄,段總
23:49:46.590 [main] INFO  org.itstack.demo.design.test.ApiTest - 測試結(jié)果:{"code":"0000","info":"單號:1000998004813441 狀態(tài):一級審批完成負(fù)責(zé)人 時間:2020-06-18 23:49:46 審批人:段總"}

Process finished with exit code 0
  • 從上述的結(jié)果可以看到我們的責(zé)任鏈已經(jīng)生效,按照責(zé)任鏈的結(jié)構(gòu)一層層審批显歧,直至最后輸出審批結(jié)束到一級完成的結(jié)果仪或。
  • 這樣責(zé)任鏈的設(shè)計方式可以方便的進(jìn)行擴(kuò)展和維護(hù),也把if語句干掉了士骤。

七范删、總結(jié)

  • 從上面代碼從if語句重構(gòu)到使用責(zé)任鏈模式開發(fā)可以看到,我們的代碼結(jié)構(gòu)變得清晰干凈了拷肌,也解決了大量if語句的使用到旦。并不是if語句不好,只不過if語句并不適合做系統(tǒng)流程設(shè)計廓块,但是在做判斷和行為邏輯處理中還是非常可以使用的契沫。
  • 在我們前面學(xué)習(xí)結(jié)構(gòu)性模式中講到過組合模式带猴,它像是一顆組合樹一樣,我們搭建出一個流程決策樹懈万。其實這樣的模式也是可以和責(zé)任鏈模型進(jìn)行組合擴(kuò)展使用拴清,而這部分的重點在于如何關(guān)聯(lián)鏈路的關(guān)聯(lián),最終的執(zhí)行都是在執(zhí)行在中間的關(guān)系鏈会通。
  • 責(zé)任鏈模式很好的處理單一職責(zé)和開閉原則口予,簡單了耦合也使對象關(guān)系更加清晰,而且外部的調(diào)用方并不需要關(guān)心責(zé)任鏈?zhǔn)侨绾芜M(jìn)行處理的(以上程序中可以把責(zé)任鏈的組合進(jìn)行包裝涕侈,在提供給外部使用)。但除了這些優(yōu)點外也需要是適當(dāng)?shù)膱鼍安胚M(jìn)行使用,避免造成性能以及編排混亂調(diào)試測試疏漏問題沦偎。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迁筛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子端三,更是在濱河造成了極大的恐慌舷礼,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郊闯,死亡現(xiàn)場離奇詭異妻献,居然都是意外死亡蛛株,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門育拨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谨履,“玉大人,你說我怎么就攤上這事至朗√敕” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵锹引,是天一觀的道長矗钟。 經(jīng)常有香客問我,道長嫌变,這世上最難降的妖魔是什么吨艇? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮腾啥,結(jié)果婚禮上东涡,老公的妹妹穿的比我還像新娘。我一直安慰自己倘待,他們只是感情好疮跑,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凸舵,像睡著了一般祖娘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啊奄,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天渐苏,我揣著相機(jī)與錄音,去河邊找鬼菇夸。 笑死琼富,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庄新。 我是一名探鬼主播鞠眉,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼择诈!你這毒婦竟也來了凡蚜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤吭从,失蹤者是張志新(化名)和其女友劉穎朝蜘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涩金,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡谱醇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年暇仲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片副渴。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡奈附,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出煮剧,到底是詐尸還是另有隱情斥滤,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布勉盅,位于F島的核電站佑颇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏草娜。R本人自食惡果不足惜挑胸,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宰闰。 院中可真熱鬧茬贵,春花似錦、人聲如沸移袍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葡盗。三九已至螟左,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戳粒,已是汗流浹背路狮。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工虫啥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留蔚约,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓涂籽,卻偏偏與公主長得像苹祟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子评雌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

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