詳解學(xué)習(xí)依賴注入(DI)與控制反轉(zhuǎn)(Ioc)

1. 前言

在學(xué)習(xí)nest.js的時(shí)候钾虐,我們都知道,這個(gè)框架采用的angular的思想梗搅,依賴注入禾唁,對(duì)于前端來說效览,這有點(diǎn)后端概念无切,所以我們現(xiàn)在來學(xué)習(xí)認(rèn)識(shí)這些設(shè)計(jì)模式。

2. 什么是依賴注入

2.1 它是設(shè)計(jì)模式

首先丐枉,依賴注入是一個(gè)設(shè)計(jì)模式哆键,因?yàn)樗鉀Q的是一類問題。這類問題是什么呢瘦锹?這類問題和依賴有關(guān)系籍嘹。

2.2 依賴倒轉(zhuǎn)原則

依賴倒轉(zhuǎn)原則(Dependence Inversion Priciple, DIP)提倡:

  • 高層模塊不應(yīng)該依賴低層模塊。兩個(gè)都應(yīng)該依賴抽象
  • 抽象不應(yīng)該依賴細(xì)節(jié)弯院,細(xì)節(jié)應(yīng)該依賴抽象
  • 針對(duì)接口編程辱士,不要針對(duì)實(shí)現(xiàn)編程

要想講明白這個(gè)設(shè)計(jì)模式得先給大家說一個(gè)現(xiàn)實(shí)場(chǎng)景的案例:主板和內(nèi)存條 大家都知道內(nèi)存條依賴主板,內(nèi)存條壞了和主板無關(guān)听绳,主板壞了也和內(nèi)存條無關(guān)颂碘,可以把電腦理解成是大的軟件系統(tǒng),任何部件相互依賴椅挣,但又彼此獨(dú)立头岔,即這些部件就是電腦中封裝的類或程序集塔拳,在電腦里這叫易插拔,在編程中這叫強(qiáng)內(nèi)聚低耦合峡竣。 內(nèi)存模塊(高層模塊)不依賴主板模塊(低層模塊)靠抑,它們依賴的是被抽象的接口(模塊依賴都應(yīng)該依賴抽象),抽象不應(yīng)該依賴細(xì)節(jié)适掰,細(xì)節(jié)應(yīng)該依賴抽象這句話說白了颂碧,就是要針對(duì)借口編程,不要對(duì)實(shí)現(xiàn)編程攻谁。無論主板稚伍、cpu、內(nèi)存都是針對(duì)接口設(shè)計(jì)的戚宦,都是標(biāo)準(zhǔn)的接口个曙,如果針對(duì)實(shí)現(xiàn)來設(shè)計(jì),內(nèi)存要對(duì)應(yīng)到具體的廠商主板受楼,內(nèi)存壞了主板也得換垦搬。

這也就是說:在編程時(shí),我們對(duì)系統(tǒng)進(jìn)行模塊化艳汽,它們之間有依賴猴贰,比如模塊A依賴模塊B 那么依據(jù)依賴倒轉(zhuǎn)原則,模塊A應(yīng)該依賴模塊B的接口河狐,而不應(yīng)該依賴模塊B的實(shí)現(xiàn)米绕。

雖然模塊A只依賴接口編程,但在運(yùn)行的時(shí)候馋艺,它還是需要有一個(gè)具體的模塊來負(fù)責(zé)模塊A需要的功能的栅干,所以模塊A在【運(yùn)行時(shí)】是需要一個(gè)【真的】模塊B,而不是它的接口捐祠。即模塊A在【運(yùn)行時(shí)】需要有一個(gè)接口的實(shí)現(xiàn)模塊作為它的屬性碱鳞。 那么這個(gè)實(shí)現(xiàn)模塊怎么來?它是怎么初始化踱蛀,然后怎么傳給模塊A的窿给? 解決這個(gè)問題的就是依賴注入。

2.3 前端的依賴注入

依賴注入更多的是后端的概念率拒,對(duì)于前端來說崩泡,很少有抽象,更別說有接口了猬膨。但是角撞,依賴注入?yún)s是一直都存在,只是許多人沒有認(rèn)出來而已。

比如用過vue的都應(yīng)該知道m(xù)ain.js靴寂,其實(shí)他就是一個(gè)依賴注入磷蜀,我們見過有這樣一段代碼。

import ElementUI from 'element-ui' // vue的ui組件-(餓了么-ui)element-ui
Vue.use(ElementUI)

其實(shí)就是我們的需要的模塊依賴vue模塊百炬,main.js就是vue模塊抽象出來的接口褐隆,這里使用Vue.use(),把我們需要的模塊vue注入進(jìn)來剖踊,然后我們就可以用它了庶弃。 這是個(gè)很普通的代碼,太正常了德澈,我們每天都會(huì)寫這些代碼歇攻。 其實(shí)依賴注入它只做兩件事:

  • 初始化被依賴的模塊
  • 注入到依賴模塊中

這個(gè)時(shí)候應(yīng)該知道了,import ElementUI from 'element-ui'梆造,初始化了被依賴的模塊缴守;而Vue.use(ElementUI)是把我們依賴的模塊注入到依賴模塊中。 我們不依賴element-ui的具體實(shí)現(xiàn)镇辉,我們只是使用他這個(gè)庫的抽象接口而已屡穗,比如它的button組件。

2.4 依賴注入的作用

看了上面我們常用的引入是依賴注入忽肛,是不是有點(diǎn)吃驚村砂?不用覺得這是什么很屌的是,關(guān)于這個(gè)我們仔細(xì)深究她的作用:

初始化被依賴的模塊 注入到依賴模塊中

我們?yōu)槭裁葱枰蕾囎⑷肽兀?1. 初始化被依賴的模塊

如果不通過依賴注入模式來初始化被依賴的模塊屹逛,那么就要依賴模塊自己去初始化了 那么問題來了:依賴模塊就耦合了被依賴模塊的初始化信息了 2. 注入到依賴模塊中

被依賴模塊已經(jīng)被其他管理器初始化了础废,那么依賴模塊要怎么獲取這個(gè)模塊呢? 有兩種方式:

  • 自己去問
  • 別人主動(dòng)給你

沒用依賴注入模式的話是1罕模,用了之后就是2 想想评腺,你需要某個(gè)東西的時(shí)候,你去找別人要手销,你需要提供別人什么信息歇僧?最簡(jiǎn)單的就是那個(gè)東西叫什么图张,即你需要提供一個(gè)名稱锋拖。 所以,方式1的問題是:依賴模塊耦合了被依賴模塊的【名稱】還有那個(gè)【別人】 而方式2解決了這個(gè)問題祸轮,讓依賴模塊只依賴需要的模塊的接口兽埃。

3. 前端代碼實(shí)例

  1. 我們首先得為模塊依賴提供抽象的接口
  2. 下來應(yīng)該能夠注冊(cè)依賴關(guān)系
  3. 在注冊(cè)這個(gè)依賴關(guān)系后有地方存儲(chǔ)它
  4. 存儲(chǔ)后,我們應(yīng)該把被依賴的模塊注入依賴模塊中
  5. 注入應(yīng)該保持被傳遞函數(shù)的作用域
  6. 被傳遞的函數(shù)應(yīng)該能夠接受自定義參數(shù)适袜,而不僅僅是依賴描述

基于Injector柄错、dependencies和函數(shù)參數(shù)名的依賴注入

設(shè)想我們有1個(gè)模塊Student,它依賴3個(gè)模塊Notebook、Pencil售貌、School

function Notebook() {}
Notebook.prototype.notebookName = function () {
  return 'this is a notebook'
}

function Pencil() {}
Pencil.prototype.printName = function () {
  return 'this is a pencil'
}

function School() {}
School.prototype.schoolName = function () {
  return '廣工大'
}

function Student() {}
Student.prototype.write = function (notebook, pencil, school) {
  if (!notebook || !pencil || !school) {
    throw new Error('Dependencies not provided!')
  }
  console.log('writing...')
  console.log(notebook)
  console.log(pencil)
  console.log(school)
  return '我擁有School给猾、Pencil和Notebook'
}

我們需要在Student中用到,它依賴的3個(gè)模塊Notebook颂跨、Pencil敢伸、School,記得依賴注入的功能:初始化被依賴的模塊恒削,注入到依賴模塊中池颈。

知道這些根據(jù)我們的目標(biāo),下面開始我們的injector接口钓丰,第一種方法:從方法中解析出參數(shù)的依賴注入

var injector = { // 依賴注入的抽象接口
  dependencies: {}, // 存儲(chǔ)被依賴的模塊
  register: function (key, value) { // 注冊(cè)初始化被依賴的模塊
    this.dependencies[key] = value
  },
  resolve: function (deps, func, scope) { // 注入到依賴的模塊中躯砰,注入應(yīng)該接受一個(gè)函數(shù),并返回一個(gè)我們需要的函數(shù)
    var paramNames = this.getParamNames(func) // 取得參數(shù)名
    var params = []
    for (var i = 0; i < paramNames.length; i++) { // 通過參數(shù)名在dependencies中取出相應(yīng)的依賴
      let d = paramNames[i]
      let depen = this.dependencies[d] || deps[i]
      if (depen) {
        params.push(depen)
      } else {
        throw new Error('缺失的依賴:' + d)
      }
    }
    // 注入依賴,執(zhí)行,并返回一個(gè)我們需要的函數(shù)
    return func.apply(scope || {}, params) // 將func作用域中的this關(guān)鍵字綁定到bind對(duì)象上携丁,bind對(duì)象可以為空
  },
  getParamNames: function (func) { // 獲取方法的參數(shù)名字
    var paramNames = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1]
    paramNames = paramNames.replace(/ /g, '')
    paramNames = paramNames.split(',')
    return paramNames // Array
  }
}

這里我們使用register方法來注冊(cè)初始化被依賴的模塊琢歇,使用dependencies來存儲(chǔ)被依賴的模塊,resolve來進(jìn)行注入梦鉴,getParamNames來獲取我們的傳遞方法的參數(shù)矿微,注入依賴,執(zhí)行尚揣,并返回一個(gè)我們需要的函數(shù)涌矢。

調(diào)用代碼:

injector.register('notebook', new Notebook()) // 注冊(cè)notebook
injector.register('pencil', new Pencil()) // 注冊(cè)pencil
var school = new School()
var student = new Student()
// 以參數(shù)的形式傳入school
var studentWrite = injector.resolve([, , school], student.write, student)
console.log(studentWrite) // "我擁有School、Pencil和Notebook"

執(zhí)行結(jié)果:

2019090701.png

上面我們通過injector(注入器快骗、注射器)向write方法提供它所需要的依賴娜庇。通過依賴注入,函數(shù)的執(zhí)行和其所依賴對(duì)象的創(chuàng)建邏輯就被解耦開來了方篮。這里我們初始化的方式有兩種:一種是通過injector.register來注冊(cè)名秀,一種是直接使用injector.resolve中的deps來注冊(cè)其依賴的。

這種方法我們是從方法中解析出參數(shù)她的參數(shù)得知他所依賴的模塊藕溅。下面來說說另外一種方法:從方法中解析出參數(shù)及參數(shù)聲明的依賴注入匕得。

var injector = { // 依賴注入的抽象接口
  dependencies: {}, // 存儲(chǔ)被依賴的模塊
  isDeclare: false, // 是否為參數(shù)聲明
  param: [], // 聲明參數(shù)存儲(chǔ)
  paramDeclare: function (param) { // 依賴注入?yún)?shù)聲明
    if (Object.prototype.toString.call(param) !== '[object Array]') {
      try {
        throw new Error('接受的是一個(gè)數(shù)組,但是卻得到一個(gè)' + typeof filterArray)
      } catch (e) {
        console.error(e)
      }
    }
    this.param = param.concat()
    console.log(this.param)
    this.isDeclare = true
  },
  register: function (key, value) { // 注冊(cè)初始化被依賴的模塊
    this.dependencies[key] = value
  },
  resolve: function (deps, func, scope) { // 注入到依賴的模塊中,注入應(yīng)該接受一個(gè)函數(shù)巾表,并返回一個(gè)我們需要的函數(shù)
    console.log(deps)
    var paramNames = this.isDeclare ? this.param : this.getParamNames(func) // 取得參數(shù)名
    if (paramNames.length === 0 && this.isDeclare) {
      throw new Error('缺失的參數(shù)聲明')
    }
    if (paramNames.length === 0 && !this.isDeclare) {
      throw new Error('該方法沒有參數(shù)依賴')
    }
    var params = []
    for (var i = 0; i < paramNames.length; i++) { // 通過參數(shù)名在dependencies中取出相應(yīng)的依賴
      let d = paramNames[i]
      let depen = this.dependencies[d] || deps[i]
      if (depen) {
        params.push(depen)
      } else {
        throw new Error('缺失的依賴:' + d)
      }
    }
    // 注入依賴,執(zhí)行,并返回一個(gè)我們需要的函數(shù)
    return func.apply(scope || {}, params) // 將func作用域中的this關(guān)鍵字綁定到bind對(duì)象上汁掠,bind對(duì)象可以為空
  },
  getParamNames: function (func) { // 獲取方法的參數(shù)名字
    var paramNames = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1]
    paramNames = paramNames.replace(/ /g, '')
    paramNames = paramNames.split(',')
    return paramNames // Array
  }
}

調(diào)用代碼1:

injector.register('notebook', new Notebook()) // 注冊(cè)notebook
injector.register('pencil', new Pencil()) // 注冊(cè)pencil
var school = new School()
var student = new Student()
// 以參數(shù)的形式傳入school
var studentWrite = injector.resolve([, , school], student.write, student)
console.log(studentWrite) // "我擁有School、Pencil和Notebook"

調(diào)用代碼2:

injector.register('notebook', new Notebook())
injector.register('pencil', new Pencil())
injector.paramDeclare(['notebook', 'pencil', 'school']) // injector.paramDeclare-依賴注入?yún)?shù)聲明
var school = new School()
var student = new Student()
var studentWrite = injector.resolve([, , school], student.write, student)
console.log(studentWrite) // "我擁有School集币、Pencil和Notebook"

4. 什么是IoC

Ioc - Inversion of Control , 即"控制反轉(zhuǎn)"考阱。在開發(fā)中, IoC 意味著你設(shè)計(jì)好的對(duì)象交給容器控制鞠苟,而不是使用傳統(tǒng)的方式乞榨,在對(duì)象內(nèi)部直接控制秽之。

如何理解好 IoC 呢?理解好 IoC的關(guān)鍵是要明確"誰控制誰吃既,控制什么考榨,為何是反轉(zhuǎn)(有反轉(zhuǎn)就應(yīng)該有正轉(zhuǎn)),哪些方面反轉(zhuǎn)了"鹦倚,我們來深入分析一下董虱。

誰控制誰,控制什么: 在傳統(tǒng)的程序設(shè)計(jì)中申鱼,我們直接在對(duì)象內(nèi)部通過 new 的方式創(chuàng)建對(duì)象愤诱,是程序主動(dòng)創(chuàng)建依賴對(duì)象;而 IoC 是有專門一個(gè)容器來創(chuàng)建這些對(duì)象捐友,即由 IoC 容器控制對(duì)象的創(chuàng)建淫半;誰控制誰?當(dāng)然是 IoC 容器控制了對(duì)象匣砖;控制什么科吭?主要是控制外部資源獲取。

為何是反轉(zhuǎn)了猴鲫,哪些方面反轉(zhuǎn)了: 有反轉(zhuǎn)就有正轉(zhuǎn)对人,傳統(tǒng)應(yīng)用程序是由我們自己在對(duì)象中主動(dòng)控制去獲取依賴對(duì)象,也就是正轉(zhuǎn)拂共;而反轉(zhuǎn)則是由容器來幫忙創(chuàng)建及注入依賴對(duì)象牺弄;為何是反轉(zhuǎn)?因?yàn)橛扇萜鲙臀覀儾檎壹白⑷胍蕾噷?duì)象宜狐,對(duì)象只是被動(dòng)的接受依賴對(duì)象势告,所以是反轉(zhuǎn)了;哪些方面反轉(zhuǎn)了抚恒?依賴對(duì)象的獲取被反轉(zhuǎn)了咱台。

5. IoC能做什么

Ioc 不是一種技術(shù),只是一種思想俭驮,一個(gè)重要的面向?qū)ο缶幊谭▌t回溺,它能指導(dǎo)我們?nèi)绾卧O(shè)計(jì)松耦合、更優(yōu)良的系統(tǒng)混萝。傳統(tǒng)應(yīng)用程序都是由我們?cè)陬悆?nèi)部主動(dòng)創(chuàng)建依賴對(duì)象遗遵,從而導(dǎo)致類與類之間高耦合,難于測(cè)試譬圣;有了 IoC 容器后瓮恭,把創(chuàng)建和查找依賴對(duì)象的控制權(quán)交給了容器雄坪,由容器注入組合對(duì)象厘熟,所以對(duì)象之間是松散耦合屯蹦,這樣也便于測(cè)試,利于功能復(fù)用绳姨,更重要的是使得程序的整個(gè)體系結(jié)構(gòu)變得非常靈活登澜。

其實(shí) IoC 對(duì)編程帶來的最大改變不是從代碼上,而是思想上飘庄,發(fā)生了"主從換位"的變化脑蠕。應(yīng)用程序本來是老大,要獲取什么資源都是主動(dòng)出擊跪削,但在 IoC思想中谴仙,應(yīng)用程序就變成被動(dòng)了,被動(dòng)的等待 IoC 容器來創(chuàng)建并注入它所需的資源了碾盐。

6. IoC 和 DI

DI - Dependency Injection晃跺,即"依賴注入":組件之間的依賴關(guān)系由容器在運(yùn)行期決定,形象的說毫玖,即由容器動(dòng)態(tài)的將某個(gè)依賴關(guān)系注入到組件之中掀虎。依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,而是為了提升組件重用的頻率付枫,并為系統(tǒng)搭建一個(gè)靈活烹玉、可擴(kuò)展的平臺(tái)。通過依賴注入機(jī)制阐滩,我們只需要通過簡(jiǎn)單的配置二打,而無需任何代碼就可指定目標(biāo)需要的資源,完成自身的業(yè)務(wù)邏輯掂榔,而不需要關(guān)心具體的資源來自何處址儒,由誰實(shí)現(xiàn)。

理解 DI 的關(guān)鍵是:"誰依賴了誰衅疙,為什么需要依賴莲趣,誰注入了誰,注入了什么"饱溢,那我們來深入分析一下:

  • 誰依賴了誰:當(dāng)然是應(yīng)用程序依賴 IoC 容器

  • 為什么需要依賴:應(yīng)用程序需要 IoC 容器來提供對(duì)象需要的外部資源

  • 誰注入誰:很明顯是 IoC 容器注入應(yīng)用程序依賴的對(duì)象

  • 注入了什么:注入某個(gè)對(duì)象所需的外部資源(包括對(duì)象喧伞、資源、常量數(shù)據(jù))

IoC 和 DI 有什么關(guān)系绩郎?其實(shí)它們是同一個(gè)概念的不同角度描述潘鲫,由于控制反轉(zhuǎn)的概念比較含糊(可能只是理解為容器控制對(duì)象這一個(gè)層面,很難讓人想到誰來維護(hù)依賴關(guān)系)肋杖,所以 2004 年大師級(jí)人物 Martin Fowler 又給出了一個(gè)新的名字:"依賴注入"溉仑,相對(duì) IoC 而言,"依賴注入" 明確描述了被注入對(duì)象依賴 IoC 容器配置依賴對(duì)象状植。

總的來說浊竟, 控制反轉(zhuǎn)(Inversion of Control)是說創(chuàng)建對(duì)象的控制權(quán)發(fā)生轉(zhuǎn)移怨喘,以前創(chuàng)建對(duì)象的主動(dòng)權(quán)和創(chuàng)建時(shí)機(jī)由應(yīng)用程序把控,而現(xiàn)在這種權(quán)利轉(zhuǎn)交給 IoC 容器振定,它就是一個(gè)專門用來創(chuàng)建對(duì)象的工廠必怜,你需要什么對(duì)象,它就給你什么對(duì)象后频。有了 IoC 容器梳庆,依賴關(guān)系就改變了,原先的依賴關(guān)系就沒了卑惜,它們都依賴 IoC容器了膏执,通過 IoC 容器來建立它們之間的關(guān)系。

控制反轉(zhuǎn):創(chuàng)建對(duì)象實(shí)例的控制權(quán)從代碼控制剝離到IOC容器控制露久,實(shí)際就是你在xml文件控制胧后,側(cè)重于原理。 依賴注入:創(chuàng)建對(duì)象實(shí)例時(shí)抱环,為這個(gè)對(duì)象注入屬性值或其它對(duì)象實(shí)例壳快,側(cè)重于實(shí)現(xiàn)。

依賴注入和控制反轉(zhuǎn)是同一概念镇草,是對(duì)同一件事情的不同描述眶痰,它們描述的角度不同。

依賴注入是從應(yīng)用程序的角度在描述:應(yīng)用程序依賴容器創(chuàng)建并注入它所需要的外部資源梯啤;

而控制反轉(zhuǎn)是從容器的角度在描述:容器控制應(yīng)用程序竖伯,由容器反向的向應(yīng)用程序注入應(yīng)用程序所需要的外部資源(對(duì)象、文件等)因宇。

相關(guān)文章:

?著作權(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
  • 文/不壞的土叔 我叫張陵礁阁,是天一觀的道長巧号。 經(jī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
  • 文/蒼蘭香墨 我猛地睜開眼修陡,長吁一口氣:“原來是場(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ú)居荒郊野嶺守林人離奇死亡,尸身上長有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
  • 我被黑心中介騙來泰國打工煤禽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铐达,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓呜师,卻偏偏與公主長得像娶桦,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汁汗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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