关于设计模式

Design Pattern 设计模式

0.0 概述:

A pattern is a solution to a problem in a context

模式是在特定环境中解决问题的一种方案

0.1 模式

  • Context:模式可适用的前提条件
  • Theme或Problem:要解决的目标问题
  • Solution:解决方案

每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心,通过这种方式,我们可以无数次地重用那些已有的解决方案,无需再重复相同的工作

GoF在1994年归纳发表了23种在软件开发中使用频率较高的设计模式,旨在用模式来统一沟通面向对象方法在分析、设计和实现间的鸿沟

0.2 软件模式

  • 软件模式是将模式的一般概念应用于软件开发领域,即软件开发的体指导思路或参照样板。
  • 对软件开发这一特定“问题”的“解法”的某种统一表示
  • 软件模式等于一定条件下的出现的问题以及解法。

实际上,在软件生存期的每一个阶段都存在着一些被认同的模式,
软件模式包括:

  • 设计模式
  • 架构模式
  • 分析模式
  • 过程模式等

软件模式的基础结构由4个部分构成:

  • 问题描述
  • 前提条件(环境或约束条件)
  • 解法
  • 效果

软件模式与具体的应用领域无关

1995年,GoF出版了设计模式圣经------《Design Patterns: Elements of Reusable Object-Oriented Software》

0.3 设计模式的定义

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性

0.4 设计模式的基本要素

  • 模式名称 (Pattern name)
  • 问题 (Problem)
  • 解决方案 (Solution)
  • 效果 (Consequences)
  • 实例代码 (Sample Code)
  • 相关设计模式 (Related Patterns)

0.5 设计模式的分类

23种设计模式

根据目的:

  • 创建型:(Creational):

    • 将软件模块中对象的创建和对象的使用分离
    • 隐藏了类的实例的创建细节
  • 结构型(Structural):用于处理类或对象的组合

    • 类结构型:关注类之间的继承和实现
    • 对象结构型:关注类和对象的组合
  • 行为型(Behavioral):关注类或对象的职责划分和交互

    • 类行为型模式:通过继承机制分配行为
    • 对象行为型模式:通过聚合分配行为

根据范围:

  • 类模式:处理类和子类之间的关系,通过继承建立,在编译时刻确定,静态
  • 对象模式:处理对象间的关系,运行时,动态

0.6 优点:

  • 设计模式融合了众多专家的经验,并给出了标准解决方案,利于开发人员沟通,可以降低开发人员理解系统的复杂度

  • 使得复用更加简便,为系统设计提供思路

  • 设计方案更加灵活,且易于修改和维护,降低开发和维护成本

  • 有助于初学者更深入地理解面向对象思想

    • 帮助初学者方便地阅读和学习现有类库与其他系统中的源代码,JAVA 的许多优秀框架都大量使用了设计模式
    • 提高软件的设计水平和代码质量

1.0 单例模式(Singleton)

单例模式
单例模式

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法

1.1 动机

  • 对于系统中的某些类来说,只有一个实例很重要

单例模式的要点有三个:

  • 某个类只能有一个实例
  • 它必须自行创建这个实例
  • 它必须自行向整个系统提供这个实例

1.2 定义

Ensure a class only has one instance, and provide a global point of access to it.

保证一个类仅有一个实例,并提供一个访问它的全局访问点

1.3 分析

单例模式类图
  • 私有构造,确保用户无法通过new关键字直接实例化它
  • 静态私有成员变量维护一个唯一实例
  • 静态公有的方法对外发布实例
public class Singleton {
    //静态私有成员变量
    private static Singleton instance = null;
    
    private Singleton() { 
        //私有构造方法
    }
    //静态公有工厂方法,返回唯一实例
    public static Singleton getInstance() {
        if (instance == null)
        instance = new Singleton();
        return instance;
    }
}

饿汉式单例类

//在类初始化时创建唯一实例
private static final Car car = new Car();
  • 饿,对象长期驻留在内存而不被调用,自己不会被调用,则饥饿,其他对象难以得到足够的内存资源,则饥饿
  • 类初始化时创建唯一实例
  • 长期占用空间

懒汉式单例类

private static Car car = null;

//在初次使用时创建唯一实例
public Car getInstance(){
    //...
    if (car == null)
        car = new Car();
    //...
}

  • 懒,同义于“懒加载”,事到临头才做,也就是第一次需要对象时才实例化
  • 多线程环境下较复杂,涉及资源访问等长操作时,极易出错,同步操作又将增加初始化开销
  • 适用单线程且实例较大的情况

内存充足且对响应时间敏感,在系统启动时预热一下所有单例类,使得全部在启动时初始化

1.4 优缺点

单例模式的优点

  • 提供了对唯一实例的受控访问。可以严格控制客户怎样以及何时访问对象,并为设计及开发团队提供了共享的概念。

  • 复用对象,由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。

  • 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

单例模式的缺点

  • 没有抽象层,难以扩展
  • 单例类的职责过重,自己负责创建自己,负责对外发布自己,在一定程度上违背了“单一职责原则”。
  • 垃圾回收的技术的不恰当应用可能导致对象状态的丢失

1.5 适用环境

  • 系统只需要或只能创建单实例

    • 业务环节要求,如单Connection
    • 资源消耗太大而只允许创建一个对象
  • 客户调用类的单个实例只允许使用单一公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

  • 系统要求固定实例数,在状态上的注意

2.0 策略模式(Strategy)

策略模式

策略模式

2.1 问题 Problem

  • 在软件系统中,有许多算法可以实现某一功能(如查找/排序的算法),一种传统的做法是将算法硬编码在一个类中,通过if或switch来区分
  • 不利于扩展

2.2 解决方案 Solution

Define a family of algorithms, encapsulate each one, and make them interchangeable

解决方案:把一系列具体的算法抽象为可替换的策略类

Strategy lets the algorithm vary independently from clients that use it.

可替换:Strategy模式使得算法可独立于客户端而变化

Strategy模式
  • Context—环境角色
    • 持有一个Strategy类的引用
  • Strategy—抽象策略角色
    • 这是一个抽象角色,此角色给出所有具体策略类所需的接口
  • Concrete Strategy—具体策略角色
    • 包装了相关的算法或行为
  • 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。

2.3 效果 Consequences

public class Context {
    //......
    public void algorithm(String type) {
        if (type == "strategyA") { 
            //算法A
        }
        else if (type == "strategyB") { 
            //算法B
        }
        else if (type == "strategyC") { 
            //算法C
        }
        //......
    }
} 


public abstract class AbstractStrategy {
    public abstract void algorithm();
} 

public class ConcreteStrategyA extends AbstractStrategy {
    public void algorithm() { 
        //算法A的实现
    }
} 

public class Context {
    private AbstractStrategy strategy;
    public void setStrategy (AbstractStrategy strategy) {
        this.strategy= strategy; // 设置使用的具体算法
    }
    public void algorithm() {
        strategy.algorithm();
    }
} 
  • 提高了系统的灵活性,策略可以灵活切换

优点

  • “开闭原则”的完美实践,可以在不修改原有系统的基础上选择算法或行为也可以灵活地增加新的算法或行为
  • 策略模式提供了管理相关的算法族的办法
  • 策略模式提供了可以替换继承关系的办法
  • 使用策略模式可以避免使用多重条件转移语句

缺点

  • 客户端负责向context注入策略,客户端负责选择并实例化具体策略,增加了客户端的使用难度
  • 策略模式将产生很多策略类

2.4 适用环境

  • 完成同一个目标在不同环境需要不同的策略
  • 一个算法使用了客户端不应该知道的算法,使用策略模式来避免对客户端暴露复杂且与算法相关的数据结构

  • 一个类定义了多个行为,并且这些行为的触发依赖于多个控制条件,避免使用多个控制条件,将相关的策略抽离到它们具体的策略类中

2.5 应用举例

Java JDK中的策略模式

  • 布局管理器LayoutManager

    • Context角色:Container类
    • Strategy角色:LayoutManager接口
    • Concrete Strategy角色:BorderLayout, FlowLayout, … …
  • Swing中的组件边框Border

    • Context角色:JComponent类
    • Strategy角色:Border接口
    • Concrete Strategy角色:TitledBorder, LineBorder, … …

3.0 工厂模式(Factory)

工厂模式
  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

3.1 问题

依赖倒置原则(Dependency-Inversion Principle)

  • 依赖于抽象,面向接口编程
简单工厂模式

在客户端需要:


Shape square=new Square();
Shape circle=new Circle();

客户端依赖于具体的类。

简单工厂模式并不属于GoF23个经典设计模式,但通常将它作为学习其他工厂模式的基础。

3.2 简单工厂模式 (Simple Factory Pattern)

also called:Static Factory Method

3.2.1 背景

  • 客户端与具体类耦合
  • 客户端选择具体类需要 繁琐的 if...else
  • 具体类的创建可能还需要初始化
  • 客户端承担过多职责,容易出错

3.2.2 定义

  • 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式
  • 可以将静态工厂方法的参数存储在配置文件中

3.2.3 优缺点

优点
  • 分割责任,免除了客户端直接创建产品对象的责任,客户端专注于“消费”产品
  • 客户端只需要知道产品对应的工厂参数即可,减少使用者需要的信息
  • 通过引入配置文件,可以在不修改任何客户代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
缺点
  • 如果工厂类集中了太多产品的创建逻辑职责过重,一旦不能正常工作,整个系统都可能受到影响

  • 使用简单工厂模式将会增加系统中类的个数,在一定程度上增加了系统的复杂度和理解难度

  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护,可以通过反射来改善

3.2.4 适用环境

  • 工厂类负责创建的对象比较少
    • 不会造成工厂方法中的业务逻辑太过复杂
    • 如果创建的对象类型很少,使用工厂模式或抽象工厂有过度设计的嫌疑
  • 客户只知道传入工厂类的参数,对于如何创建对象不关心
    • 客户只需要知道类型所对应的参数

3.3 工厂方法模式 (Factory Method)

Factory Method

3.3.1 动机

  • 简单工厂 存在过多的条件分支语句,难以维护
  • 简单工厂 难以扩展,扩展需要修改工厂逻辑,违背了开闭原则

3.3.2 定义

工厂模式-类图
  • 工厂父类 定义了创建产品的接口(规范)

Factory Method lets a class defer instantiation to subclasses.

  • 工厂子类负责具体产品的创建

3.3.3 分析

  • 是简单工厂的进一步抽象,克服了简单工厂的不易扩展,保持其优点

  • 父类工厂负责创建的规范,具体工厂负责实现,引入新产品符合开闭原则

  • 谨防工厂模式退化为简单工厂

3.3.4 优缺点

优点
  • 符合Demeter法则,尽量少的信息量,用户只需要关心所需产品对应的工厂

  • 使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部

  • 加入新产品时只添加一个具体工厂和具体产品即可。符合“开闭原则

缺点
  • 添加一个新的产品,需要添加一个对应的工厂,工厂和商品成对出现,在一定程度上增加了系统的复杂度,类的增多增加系统开销

  • 由于考虑到系统的可扩展性,引入抽象层,在客户代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度

3.3.5 适应环境

  • 一个产品对应一个工厂
  • 一个类不知道它所需要的对象的类
    • 客户需要知道创建具体产品的工厂类
  • 使用时用抽象产品声明
    • 运行时确定,符合Liskov替换原则,使得系统更容易扩展

3.4 抽象工厂模式(Abstract Factory)

抽象工厂模式

3.4.1 动机

工厂模式一个工厂只能生产一种产品,而业务需要创建一系列产品

  • 产品等级结构:产品等级结构即产品的继承结构

    • 不同工厂生产同种类型的产品
    • 如:一个抽象类是电视,其子类有小米电视、乐视电视,抽象电视是父类,而具体品牌的电视是其子类
  • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品

    • 同一个工厂生产的所有产品的类型构成产品族
    • 如小米工厂生产:小米手机,小米电视...小米全家桶就是小米产品族

抽象工厂是工厂模式的升级版

  • 工厂方法模式针对的是一个产品等级结构,不同工厂生产一种同类产品
  • 抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建,不同工厂生产一系列产品
一个具体工厂生产方,圆,椭圆等一系列产品

3.4.2 定义

抽象工厂模式(Abstract Factory Pattern)

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类

抽象工厂-类图

3.4.3 优缺点

优点
  • 所有工厂模式:分离了具体类的生产和消费
  • 应用抽象工厂模式可以实现高内聚低耦合的设计目的
    • 当一个产品族中的多个对象被设计成一起工作时,保证客户始终只使用同一个产品族中的对象
    • 一系列具体产品的构建被通过“产品族”的概念耦合在一个具体的工厂中
  • 易于增加新的具体工厂(也即产品族),无须修改已有系统,符合“开闭原则”
缺点:
  • 难以扩展新的产品,整个产品体系都要修改,
  • 开闭原则有所倾斜(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)

3.4.4 适应环境

在以下情况下可以使用抽象工厂模式:

  • 对于所有类型的工厂模式,一个系统不应当依赖于产品类实例被创建、组合和表达的细节
  • 需要同时使用同一工厂的一系列产品,并可能切换产品族
  • 产品之间形成产品族,系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户依赖于抽象产品
Java AWT 组件

4.0 组合模式(Composite)

Composite
image.png

4.1 动机

文件树结构

在树形结构中,希望一致对待集合对象和个体对象

4.2 定义

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

组合多个对象形成树形结构以表示“整体-部分”的结构层次。组合模式使客户对单个对象(即叶子对象)和组合对象(即容器对象)的使用
具有一致性

组合模式的设计类图
  • Component—抽象构件角色
    • 给出共有的接口及其默认行为
  • Leaf—叶子构件角色
    • 没有下级的子对象,定义出参加组合的原始对象的行为
  • Composite—容器构件角色
    • 给出树枝构件对象的行为

4.3 优缺点

优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易
  • 客户调用简单,客户可以一致地使用组合结构或其中单个对象
  • 树形结构易扩展,添加容器构建和叶子构建都可以

缺点

  • 使设计变得更加抽象
    • 如果组件的业务很复杂,实现起来比较麻烦
    • 容器构件和叶子构件存在行为差异,抽象为一致的构建事实上是对行为差异的掩耳盗铃,而业务复杂也会增加行为差异
  • 增加新构件时,难以对容器中的构件类型进行限制

4.4 适用环境

  • 希望一致性对待整体和部分,忽略差异
  • 让客户能够忽略不同对象层次的变化针对抽象构件编程,无须关心对象层次结构的细节

5.0 观察者模式(Observer)

Observer
Observer 关注对象行为

5.1 动机

建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应

  • 发生改变的对象:观察目标(主题)
  • 被通知的对象:观察者
  • 主题和观察者 一对多
  • 观察者之间没有关系
  • 主题提供订阅和取消订阅的服务,类似于订报纸,关注

5.2 定义

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

also called:

  • 发布-订阅模式(Publish-Subscribe)
  • 模型-视图模式(Model-View)
  • 源-监听器模式(Source-Listener)
  • 从属者模式(Dependents)
观察者模式——类图
  • Subject—抽象主题角色

    • 所有的主题角色都维护所有对观察者对象的引用,所以放在抽象层
  • Observer—抽象观察者角色

    • 向主题对象暴露接受通知的方法,以便响应通知
  • ConcreteSubject—具体主题角色

    • 将有关状态存入具体观察者对象;
    • 在具体主题的内部状态改变时,通知所有已订阅的观察者
  • ConcreteObserver—具体观察者角色

    • 实现具体的通知响应逻辑

5.3 优缺点

优点

  • 表示层和数据逻辑层分离,不同观察者对同一通知表现出不一样的行为
  • 定义了稳定的消息传递机制,通过接口定义观察者规范,具体观察者实现同一接口
  • 观察者模式支持广播通信
  • 观察者模式符合“开闭原则”,添加新的观察者类型或主题类型,不需要修改主要的程序

缺点

  • 主题对象的订阅者过多将导致线性遍历通知耗时太长,可以考虑通过多线程优化

  • 观察者和主题必须职责分明,如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

  • 观察者只知道 订阅主题发生了变化,不知道变化的原因

5.4 适用环境

When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.

当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用

  • 观察者依赖于主题的改变而改变

When a change to one object requires changing others, and you don't know how many objects need to be changed.

当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象需要因之改变

  • 订阅者的数目是不定的

When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的

  • 希望一致性地通知订阅者,不关心具体的通知响应行为

总结

创建型设计模式 (Creational)

  • Singleton(单例)

    • 保证一个类仅有一个实例,并提供一个访问它的全局访问点
  • Factory Method(工厂方法)

    • 一个产品一个工厂,所有产品生产一种产品
    • 抽象工厂定义生产抽象产品的规范,具体工厂生产具体产品
  • Abstract Factory(抽象工厂)

    • 每个工厂负责生产一系列产品
    • 不同工厂能生产同一种产品
  • Builder(建造者)

    • 将一个复杂对象的创建与它的表示分离,使得同样的创建过程可以创建不同的表示
  • Prototype(原型)

    • 用原型实例指定创建对象的种类,并通过拷贝这个原型来创建新的对象

结构型设计模式 (Structural)

  • Adapter(适配器)
    • 转接口,一般用于老系统的维护,迫不得已而用
    • 使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
  • Bridge(桥接)
    • 将抽象部分与它的实现部分分离,使它们都可以独立地变化
  • Composite(组合)
    • 将对象组合成树形接口以表示“部分-整体”的层次结构,使得客户对单个对象和复合对象的使用具有一致性
  • Decorator(装饰)
    • 动态地给一个对象添加一些额外的职责
    • 就扩展功能而言,此模式比生成子类方式更为灵活
  • Facade(外观)
    • 为子系统中的一组接口提供一个一致的界面
    • 此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
  • Flyweight(享元)
    • 运用共享技术有效地支持大量细粒度的对象
  • Proxy(代理)
    • 为其他对象提供一个代理以控制对这个对象的访问

行为型设计模式 (Behavioral)

  • Interpreter(解释器)
    • 给定一个语言,定义文法表示,定义解释器
    • 该解释器使用该表示来解释语言中的句子
  • Template Method(模板方法)
    • 定义一个操作中的算法骨架,将一些步骤延迟到子类中
    • 使得子类可以不改变一个算法的结构即可重定义该算法中某些特定步+骤
  • Chain of Responsibility(责任链)
    • 解耦:请求的发送者 <-->请求的接收者
  • Command(命令)
    • 将一个请求封装为一个对象,使得可以用不同的请求对客户进行参数化
    • 对请求排队或记录请求日志,支持撤销操作
  • Iterator(迭代器)
    • 提供一种方法顺序访问一个聚合对象中各个元素,而无需暴露该对象的内部表示
  • Mediator(中介者)
    • 用一个中介对象来封装一系列的对象交互
    • 中介者使各对象不需要显式地相互引用(松散耦合),而且可以独立地改变它们之间的交互
  • Memento(备忘录)
    • 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
    • 便于将对象恢复到保存的状态,类似游戏存档功能
  • Observer(观察者)
    • 定义对象间一对多的依赖关系
    • 主题状态发生变化时,所以订阅者都将得到通知并为之响应
  • State(状态)
    • 允许一个对象在其内部状态改变时改变它的行为
    • 对象看起来似乎修改了它所属的类
    • 关注状态(属性)
  • Strategy(策略)
    • 定义一系列的算法,对其进行封装,使其可以互相替换
    • 使得算法的变化可以独立于使用它的客户
  • Visitor(访问者)
    • 表示一个作用于某对象结构中的各元素的操作
    • 使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270