如何 “干掉” if...else

前言

if...else 是所有高級(jí)編程語言都有的必備功能。但現(xiàn)實(shí)中的代碼往往存在著過多的 if...else扔傅。雖然 if...else 是必須的询兴,但濫用 if...else 會(huì)對(duì)代碼的可讀性跟啤、可維護(hù)性造成很大傷害诽表,進(jìn)而危害到整個(gè)軟件系統(tǒng)。現(xiàn)在軟件開發(fā)領(lǐng)域出現(xiàn)了很多新技術(shù)腥光、新概念,但 if...else 這種基本的程序形式并沒有發(fā)生太大變化糊秆。使用好 if...else 不僅對(duì)于現(xiàn)在武福,而且對(duì)于將來,都是十分有意義的痘番。今天我們就來看看如何“干掉”代碼中的 if...else捉片,還代碼以清爽。

問題一:if...else 過多

問題表現(xiàn)

if...else 過多的代碼可以抽象為下面這段代碼汞舱。其中只列出5個(gè)邏輯分支伍纫,但實(shí)際工作中,能見到一個(gè)方法包含10個(gè)昂芜、20個(gè)甚至更多的邏輯分支的情況莹规。另外,if...else 過多通常會(huì)伴隨著另兩個(gè)問題:邏輯表達(dá)式復(fù)雜和 if...else 嵌套過深泌神。對(duì)于后兩個(gè)問題良漱,本文將在下面兩節(jié)介紹。本節(jié)先來討論 if...else 過多的情況欢际。

if (condition1) {
    
} else if (condition2) {
    
} else if (condition3) {
    
} else if (condition4) {
    
} else {
    
}

通常母市,if...else 過多的方法,通乘鹎鳎可讀性和可擴(kuò)展性都不好患久。從軟件設(shè)計(jì)角度講,代碼中存在過多的 if...else 往往意味著這段代碼違反了違反單一職責(zé)原則和開閉原則。因?yàn)樵趯?shí)際的項(xiàng)目中蒋失,需求往往是不斷變化的返帕,新需求也層出不窮。所以高镐,軟件系統(tǒng)的擴(kuò)展性是非常重要的溉旋。而解決 if...else 過多問題的最大意義,往往就在于提高代碼的可擴(kuò)展性嫉髓。

如何解決

接下來我們來看如何解決 if...else 過多的問題观腊。下面我列出了一些解決方法。

  1. 表驅(qū)動(dòng)
  2. 職責(zé)鏈模式
  3. 注解驅(qū)動(dòng)
  4. 事件驅(qū)動(dòng)
  5. 有限狀態(tài)機(jī)
  6. Optional
  7. Assert
  8. 多態(tài)

方法一:表驅(qū)動(dòng)

介紹

對(duì)于邏輯表達(dá)模式固定的 if...else 代碼算行,可以通過某種映射關(guān)系梧油,將邏輯表達(dá)式用表格的方式表示;再使用表格查找的方式州邢,找到某個(gè)輸入所對(duì)應(yīng)的處理函數(shù)儡陨,使用這個(gè)處理函數(shù)進(jìn)行運(yùn)算。

適用場(chǎng)景

邏輯表達(dá)模式固定的 if...else

實(shí)現(xiàn)與示例

if (param.equals(value1)) {
    doAction1(someParams);
} else if (param.equals(value2)) {
    doAction2(someParams);
} else if (param.equals(value3)) {
    doAction3(someParams);
}
// ...

可重構(gòu)為

Map<?, Function<?> action> actionMappings = new HashMap<>(); // 這里泛型 ? 是為方便演示量淌,實(shí)際可替換為你需要的類型

// When init
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});

// 省略 null 判斷
actionMappings.get(param).apply(someParams);

上面的示例使用了 Java 8 的 Lambda 和 Functional Interface骗村,這里不做講解。

表的映射關(guān)系呀枢,可以采用集中的方式胚股,也可以采用分散的方式,即每個(gè)處理類自行注冊(cè)裙秋。也可以通過配置文件的方式表達(dá)琅拌。總之摘刑,形式有很多进宝。

還有一些問題,其中的條件表達(dá)式并不像上例中的那樣簡(jiǎn)單枷恕,但稍加變換党晋,同樣可以應(yīng)用表驅(qū)動(dòng)。下面借用《編程珠璣》中的一個(gè)稅金計(jì)算的例子:

if income <= 2200
  tax = 0
else if income <= 2700
  tax = 0.14 * (income - 2200)
else if income <= 3200
  tax = 70 + 0.15 * (income - 2700)
else if income <= 3700
  tax = 145 + 0.16 * (income - 3200)
......
else
  tax = 53090 + 0.7 * (income - 102200)

對(duì)于上面的代碼徐块,其實(shí)只需將稅金的計(jì)算公式提取出來隶校,將每一檔的標(biāo)準(zhǔn)提取到一個(gè)表格,在加上一個(gè)循環(huán)即可蛹锰。具體重構(gòu)之后的代碼不給出深胳,大家自己思考。

方法二:職責(zé)鏈模式

介紹

當(dāng) if...else 中的條件表達(dá)式靈活多變铜犬,無法將條件中的數(shù)據(jù)抽象為表格并用統(tǒng)一的方式進(jìn)行判斷時(shí)舞终,這時(shí)應(yīng)將對(duì)條件的判斷權(quán)交給每個(gè)功能組件轻庆。并用鏈的形式將這些組件串聯(lián)起來,形成完整的功能敛劝。

適用場(chǎng)景

條件表達(dá)式靈活多變余爆,沒有統(tǒng)一的形式。

實(shí)現(xiàn)與示例

職責(zé)鏈的模式在開源框架的 Filter夸盟、Interceptor 功能的實(shí)現(xiàn)中可以見到很多蛾方。下面看一下通用的使用模式:

重構(gòu)前:

public void handle(request) {
    if (handlerA.canHandle(request)) {
        handlerA.handleRequest(request);
    } else if (handlerB.canHandle(request)) {
        handlerB.handleRequest(request);
    } else if (handlerC.canHandle(request)) {
        handlerC.handleRequest(request);
    }
}

重構(gòu)后:

public void handle(request) {
  handlerA.handleRequest(request);
}

public abstract class Handler {
  protected Handler next;
  public abstract void handleRequest(Request request);
  public void setNext(Handler next) { this.next = next; }
}

public class HandlerA extends Handler {
  public void handleRequest(Request request) {
    if (canHandle(request)) doHandle(request);
    else if (next != null) next.handleRequest(request);
  }
}

當(dāng)然,示例中的重構(gòu)前的代碼為了表達(dá)清楚上陕,做了一些類和方法的抽取重構(gòu)∽椋現(xiàn)實(shí)中,更多的是平鋪式的代碼實(shí)現(xiàn)释簿。

注:職責(zé)鏈的控制模式

職責(zé)鏈模式在具體實(shí)現(xiàn)過程中亚隅,會(huì)有一些不同的形式。從鏈的調(diào)用控制角度看庶溶,可分為外部控制和內(nèi)部控制兩種煮纵。

外部控制不靈活,但是減少了實(shí)現(xiàn)難度偏螺。職責(zé)鏈上某一環(huán)上的具體實(shí)現(xiàn)不用考慮對(duì)下一環(huán)的調(diào)用行疏,因?yàn)橥獠拷y(tǒng)一控制了。但是一般的外部控制也不能實(shí)現(xiàn)嵌套調(diào)用套像。如果有嵌套調(diào)用酿联,并且希望由外部控制職責(zé)鏈的調(diào)用,實(shí)現(xiàn)起來會(huì)稍微復(fù)雜凉夯。具體可以參考 Spring Web Interceptor 機(jī)制的實(shí)現(xiàn)方法货葬。

內(nèi)部控制就比較靈活采幌,可以由具體的實(shí)現(xiàn)來決定是否需要調(diào)用鏈上的下一環(huán)劲够。但如果調(diào)用控制模式是固定的,那這樣的實(shí)現(xiàn)對(duì)于使用者來說是不便的休傍。

設(shè)計(jì)模式在具體使用中會(huì)有很多變種征绎,大家需要靈活掌握

方法三:注解驅(qū)動(dòng)

介紹

通過 Java 注解(或其它語言的類似機(jī)制)定義執(zhí)行某個(gè)方法的條件。在程序執(zhí)行時(shí)磨取,通過對(duì)比入?yún)⑴c注解中定義的條件是否匹配人柿,再?zèng)Q定是否調(diào)用此方法。具體實(shí)現(xiàn)時(shí)忙厌,可以采用表驅(qū)動(dòng)或職責(zé)鏈的方式實(shí)現(xiàn)凫岖。

適用場(chǎng)景

適合條件分支很多多,對(duì)程序擴(kuò)展性和易用性均有較高要求的場(chǎng)景逢净。通常是某個(gè)系統(tǒng)中經(jīng)常遇到新需求的核心功能哥放。

實(shí)現(xiàn)與示例

很多框架中都能看到這種模式的使用歼指,比如常見的 Spring MVC。因?yàn)檫@些框架很常用甥雕,demo 隨處可見踩身,所以這里不再上具體的演示代碼了。

這個(gè)模式的重點(diǎn)在于實(shí)現(xiàn)∩缏叮現(xiàn)有的框架都是用于實(shí)現(xiàn)某一特定領(lǐng)域的功能挟阻,例如 MVC。故業(yè)務(wù)系統(tǒng)如采用此模式需自行實(shí)現(xiàn)相關(guān)核心功能峭弟。主要會(huì)涉及反射附鸽、職責(zé)鏈等技術(shù)。具體的實(shí)現(xiàn)這里就不做演示了孟害。

方法四:事件驅(qū)動(dòng)

介紹

通過關(guān)聯(lián)不同的事件類型和對(duì)應(yīng)的處理機(jī)制拒炎,來實(shí)現(xiàn)復(fù)雜的邏輯,同時(shí)達(dá)到解耦的目的挨务。

適用場(chǎng)景

從理論角度講击你,事件驅(qū)動(dòng)可以看做是表驅(qū)動(dòng)的一種,但從實(shí)踐角度講谎柄,事件驅(qū)動(dòng)和前面提到的表驅(qū)動(dòng)有多處不同丁侄。具體來說:

  1. 表驅(qū)動(dòng)通常是一對(duì)一的關(guān)系;事件驅(qū)動(dòng)通常是一對(duì)多朝巫;
  2. 表驅(qū)動(dòng)中鸿摇,觸發(fā)和執(zhí)行通常是強(qiáng)依賴;事件驅(qū)動(dòng)中劈猿,觸發(fā)和執(zhí)行是弱依賴

正是上述兩者不同拙吉,導(dǎo)致了兩者適用場(chǎng)景的不同。具體來說揪荣,事件驅(qū)動(dòng)可用于如訂單支付完成觸發(fā)庫(kù)存筷黔、物流、積分等功能仗颈。

實(shí)現(xiàn)與示例

實(shí)現(xiàn)方式上佛舱,單機(jī)的實(shí)踐驅(qū)動(dòng)可以使用 Guava、Spring 等框架實(shí)現(xiàn)挨决。分布式的則一般通過各種消息隊(duì)列方式實(shí)現(xiàn)请祖。但是因?yàn)檫@里主要討論的是消除 if...else,所以主要是面向單機(jī)問題域脖祈。因?yàn)樯婕熬唧w技術(shù)肆捕,所以此模式代碼不做演示。

方法五:有限狀態(tài)機(jī)

介紹

有限狀態(tài)機(jī)通常被稱為狀態(tài)機(jī)(無限狀態(tài)機(jī)這個(gè)概念可以忽略)盖高。先引用維基百科上的定義:

有限狀態(tài)機(jī)(英語:finite-state machine慎陵,縮寫:FSM)掏秩,簡(jiǎn)稱狀態(tài)機(jī),是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型荆姆。

其實(shí)蒙幻,狀態(tài)機(jī)也可以看做是表驅(qū)動(dòng)的一種,其實(shí)就是當(dāng)前狀態(tài)和事件兩者組合與處理函數(shù)的一種對(duì)應(yīng)關(guān)系胆筒。當(dāng)然邮破,處理成功之后還會(huì)有一個(gè)狀態(tài)轉(zhuǎn)移處理。

適用場(chǎng)景

雖然現(xiàn)在互聯(lián)網(wǎng)后端服務(wù)都在強(qiáng)調(diào)無狀態(tài)仆救,但這并不意味著不能使用狀態(tài)機(jī)這種設(shè)計(jì)抒和。其實(shí),在很多場(chǎng)景中彤蔽,如協(xié)議棧摧莽、訂單處理等功能中,狀態(tài)機(jī)有這其天然的優(yōu)勢(shì)顿痪。因?yàn)檫@些場(chǎng)景中天然存在著狀態(tài)和狀態(tài)的流轉(zhuǎn)镊辕。

實(shí)現(xiàn)與示例

實(shí)現(xiàn)狀態(tài)機(jī)設(shè)計(jì)首先需要有相應(yīng)的框架,這個(gè)框架需要實(shí)現(xiàn)至少一種狀態(tài)機(jī)定義功能蚁袭,以及對(duì)于的調(diào)用路由功能征懈。狀態(tài)機(jī)定義可以使用 DSL 或者注解的方式。原理不復(fù)雜揩悄,掌握了注解卖哎、反射等功能的同學(xué)應(yīng)該可以很容易實(shí)現(xiàn)。

參考技術(shù):

上述框架只是起到一個(gè)參考的作用晰韵,如果涉及到具體項(xiàng)目,需要根據(jù)業(yè)務(wù)特點(diǎn)自行實(shí)現(xiàn)狀態(tài)機(jī)的核心功能熟妓。

方法六:Optional

介紹

Java 代碼中的一部分 if...else 是由非空檢查導(dǎo)致的雪猪。因此,降低這部分帶來的 if...else 也就能降低整體的 if...else 的個(gè)數(shù)起愈。

Java 從 8 開始引入了 Optional 類只恨,用于表示可能為空的對(duì)象译仗。這個(gè)類提供了很多方法,用于相關(guān)的操作官觅,可以用于消除 if...else纵菌。開源框架 Guava 和 Scala 語言也提供了類似的功能。

使用場(chǎng)景

有較多用于非空判斷的 if...else休涤。

實(shí)現(xiàn)與示例

傳統(tǒng)寫法:

String str = "Hello World!";
if (str != null) {
    System.out.println(str);
} else {
    System.out.println("Null");
}

使用 Optional 之后:

Optional<String> strOptional = Optional.of("Hello World!");
strOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));

Optional 還有很多方法咱圆,這里不一一介紹了。但請(qǐng)注意功氨,不要使用 get()isPresent() 方法序苏,否則和傳統(tǒng)的 if...else 無異。

擴(kuò)展:Kotlin Null Safety

Kotlin 帶有一個(gè)被稱為 Null Safety 的特性:

bob?.department?.head?.name

對(duì)于一個(gè)鏈?zhǔn)秸{(diào)用捷凄,在 Kotlin 語言中可以通過 ?. 避免空指針異常忱详。如果某一環(huán)為 null,那整個(gè)鏈?zhǔn)奖磉_(dá)式的值便為 null跺涤。

方法七:Assert 模式

介紹

上一個(gè)方法適用于解決非空檢查場(chǎng)景所導(dǎo)致的 if...else匈睁,類似的場(chǎng)景還有各種參數(shù)驗(yàn)證,比如還有字符串不為空等等桶错。很多框架類庫(kù)软舌,例如 Spring、Apache Commons 都提供了工具里牛曹,用于實(shí)現(xiàn)這種通用的功能佛点。這樣大家就不必自行編寫 if...else 了。

使用場(chǎng)景

通常用于各種參數(shù)校驗(yàn)

擴(kuò)展:Bean Validation

類似上一個(gè)方法黎比,介紹 Assert 模式順便介紹一個(gè)有類似作用的技術(shù) —— Bean Validation超营。Bean Validation 是 Java EE 規(guī)范中的一個(gè)。Bean Validation 通過在 Java Bean 上用注解的方式定義驗(yàn)證標(biāo)準(zhǔn)阅虫,然后通過框架統(tǒng)一進(jìn)行驗(yàn)證演闭。也可以起到了減少 if...else 的作用。

方法八:多態(tài)

介紹

使用面向?qū)ο蟮亩鄳B(tài)颓帝,也可以起到消除 if...else 的作用米碰。在代碼重構(gòu)這本書中,對(duì)此也有介紹:https://refactoring.com/catalog/replaceConditionalWithPolymorphism.html

使用場(chǎng)景

鏈接中給出的示例比較簡(jiǎn)單购城,無法體現(xiàn)適合使用多態(tài)消除 if...else 的具體場(chǎng)景吕座。一般來說,當(dāng)一個(gè)類中的多個(gè)方法都有類似于示例中的 if...else 判斷瘪板,且條件相同吴趴,那就可以考慮使用多態(tài)的方式消除 if...else。

同時(shí)侮攀,使用多態(tài)也不是徹底消除 if...else锣枝。而是將 if...else 合并轉(zhuǎn)移到了對(duì)象的創(chuàng)建階段厢拭。在創(chuàng)建階段的 if..,我們可以使用前面介紹的方法處理撇叁。

小結(jié)

上面這節(jié)介紹了 if...else 過多所帶來的問題供鸠,以及相應(yīng)的解決方法。除了本節(jié)介紹的方法陨闹,還有一些其它的方法回季。比如,在《重構(gòu)與模式》一書中就介紹了“用 Strategy 替換條件邏輯”正林、“用 State 替換狀態(tài)改變條件語句”和“用 Command 替換條件調(diào)度程序”這三個(gè)方法泡一。其中的“Command 模式”,其思想同本文的“表驅(qū)動(dòng)”方法大體一致觅廓。另兩種方法鼻忠,因?yàn)樵凇吨貥?gòu)與模式》一書中已做詳細(xì)講解,這里就不再重復(fù)杈绸。

何時(shí)使用何種方法帖蔓,取決于面對(duì)的問題的類型。上面介紹的一些適用場(chǎng)景瞳脓,只是一些建議塑娇,更多的需要開發(fā)人員自己的思考。

問題二:if...else 嵌套過深

問題表現(xiàn)

if...else 多通常并不是最嚴(yán)重的的問題劫侧。有的代碼 if...else 不僅個(gè)數(shù)多埋酬,而且 if...else 之間嵌套的很深,也很復(fù)雜烧栋,導(dǎo)致代碼可讀性很差写妥,自然也就難以維護(hù)。

if (condition1) {
    action1();
    if (condition2) {
        action2();
        if (condition3) {
            action3();
            if (condition4) {
                action4();
            }
        }
    }
}

if...else 嵌套過深會(huì)嚴(yán)重地影響代碼的可讀性审姓。當(dāng)然珍特,也會(huì)有上一節(jié)提到的兩個(gè)問題。

如何解決

上一節(jié)介紹的方法也可用用來解決本節(jié)的問題魔吐,所以對(duì)于上面的方法扎筒,此節(jié)不做重復(fù)介紹。這一節(jié)重點(diǎn)一些方法酬姆,這些方法并不會(huì)降低 if...else 的個(gè)數(shù)嗜桌,但是會(huì)提高代碼的可讀性:

  1. 抽取方法
  2. 衛(wèi)語句

方法一:抽取方法

介紹

抽取方法是代碼重構(gòu)的一種手段。定義很容易理解轴踱,就是將一段代碼抽取出來症脂,放入另一個(gè)單獨(dú)定義的方法谚赎。借用 https://refactoring.com/catalog/extractMethod.html 中的定義:

適用場(chǎng)景

if...else 嵌套嚴(yán)重的代碼淫僻,通秤张瘢可讀性很差。故在進(jìn)行大型重構(gòu)前雳灵,需先進(jìn)行小幅調(diào)整棕所,提高其代碼可讀性。抽取方法便是最常用的一種調(diào)整手段悯辙。

實(shí)現(xiàn)與示例

重構(gòu)前:

public void add(Object element) {
  if (!readOnly) {
    int newSize = size + 1;
    if (newSize > elements.length) {
      Object[] newElements = new Object[elements.length + 10];
      for (int i = 0; i < size; i++) {
        newElements[i] = elements[i];
      }
      
      elements = newElements
    }
    elements[size++] = element;
  }
}

重構(gòu)后:

public void add(Object element) {
  if (readOnly) {
    return;
  }
  
  if (overCapacity()) {
    grow();
  }
  
  addElement(element);
}

方法二:衛(wèi)語句

介紹

在代碼重構(gòu)中琳省,有一個(gè)方法被稱為“使用衛(wèi)語句替代嵌套條件語句”https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html。直接看代碼:

double getPayAmount() {
    double result;
    if (_isDead) result = deadAmount();
    else {
        if (_isSeparated) result = separatedAmount();
        else {
            if (_isRetired) result = retiredAmount();
            else result = normalPayAmount();
        };
    }
    return result;
}

重構(gòu)之后

double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired) return retiredAmount();
    return normalPayAmount();
}

使用場(chǎng)景

當(dāng)看到一個(gè)方法中躲撰,某一層代碼塊都被一個(gè) if...else 完整控制時(shí)针贬,通常可以采用衛(wèi)語句拢蛋。

問題三:if...else 表達(dá)式過于復(fù)雜

問題表現(xiàn)

if...else 所導(dǎo)致的第三個(gè)問題來自過于復(fù)雜的條件表達(dá)式桦他。下面給個(gè)簡(jiǎn)單的例子,當(dāng) condition 1谆棱、2快压、3、4 分別為 true垃瞧、false蔫劣,請(qǐng)大家排列組合一下下面表達(dá)式的結(jié)果。

if ((condition1 && condition2 ) || ((condition2 || condition3) && condition4)) {
  
}

我想沒人愿意干上面的事情个从。關(guān)鍵是脉幢,這一大坨表達(dá)式的含義是什么?關(guān)鍵便在于嗦锐,當(dāng)不知道表達(dá)式的含義時(shí)鸵隧,沒人愿意推斷它的結(jié)果。

所以意推,表達(dá)式復(fù)雜豆瘫,并不一定是錯(cuò)。但是表達(dá)式難以讓人理解就不好了菊值。

如何解決

對(duì)于 if...else 表達(dá)式復(fù)雜的問題外驱,主要用代碼重構(gòu)中的抽取方法、移動(dòng)方法等手段解決腻窒。因?yàn)檫@些方法在《代碼重構(gòu)》一書中都有介紹昵宇,所以這里不再重復(fù)。

總結(jié)

本文一個(gè)介紹了10種(算上擴(kuò)展有12種)用于消除儿子、簡(jiǎn)化 if...else 的方法瓦哎。還有一些方法,如通過策略模式、狀態(tài)模式等手段消除 if...else 在《重構(gòu)與模式》一書中也有介紹蒋譬。

正如前言所說割岛,if...else 是代碼中的重要組成部分,但是過度犯助、不必要地使用 if...else癣漆,會(huì)對(duì)代碼的可讀性、可擴(kuò)展性造成負(fù)面影響剂买,進(jìn)而影響到整個(gè)軟件系統(tǒng)惠爽。

“干掉”if...else 的能力高低反映的是程序員對(duì)軟件重構(gòu)、設(shè)計(jì)模式瞬哼、面向?qū)ο笤O(shè)計(jì)婚肆、架構(gòu)模式、數(shù)據(jù)結(jié)構(gòu)等多方面技術(shù)的綜合運(yùn)用能力坐慰,反映的是程序員的內(nèi)功旬痹。要合理使用 if...else,不能沒有設(shè)計(jì)讨越,也不能過度設(shè)計(jì)两残。這些對(duì)技術(shù)的綜合、合理地運(yùn)用都需要程序員在工作中不斷的摸索總結(jié)把跨。

我的技術(shù)公眾號(hào)“編走編想”
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末人弓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子着逐,更是在濱河造成了極大的恐慌崔赌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耸别,死亡現(xiàn)場(chǎng)離奇詭異健芭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秀姐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門慈迈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人省有,你說我怎么就攤上這事痒留。” “怎么了蠢沿?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵伸头,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我舷蟀,道長(zhǎng)恤磷,這世上最難降的妖魔是什么面哼? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮扫步,結(jié)果婚禮上魔策,老公的妹妹穿的比我還像新娘。我一直安慰自己锌妻,他們只是感情好代乃,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布旬牲。 她就那樣靜靜地躺著仿粹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪原茅。 梳的紋絲不亂的頭發(fā)上吭历,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音擂橘,去河邊找鬼晌区。 笑死,一個(gè)胖子當(dāng)著我的面吹牛通贞,可吹牛的內(nèi)容都是我干的朗若。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼昌罩,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼哭懈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起茎用,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤遣总,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后轨功,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旭斥,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年古涧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垂券。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡羡滑,死狀恐怖圆米,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啄栓,我是刑警寧澤娄帖,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站昙楚,受9級(jí)特大地震影響近速,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一削葱、第九天 我趴在偏房一處隱蔽的房頂上張望奖亚。 院中可真熱鬧,春花似錦析砸、人聲如沸昔字。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽作郭。三九已至,卻和暖如春弦疮,著一層夾襖步出監(jiān)牢的瞬間夹攒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工胁塞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咏尝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓啸罢,卻偏偏與公主長(zhǎng)得像编检,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扰才,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344