第四天:工厂方法模式、抽象工厂模式

1. 工厂模式

1.1 概述

工厂模式(Factory Pattern)是一种创建型设计模式,提供了一种将对象创建的过程与对象的使用分离的机制。它通过将实例化对象的逻辑封装到一个工厂类中,从而减少客户端和具体类的耦合。这使得代码更加灵活和易于维护,尤其是当我们需要创建不同种类的对象时。

Java 中,万物皆对象,这些对象都需要创建,如果创建的时候直接 new 该对象,就会对该对象耦合严重,假如我们要更换对象,所有 new 对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的。所以说,工厂模式最大的优点就是:解耦

工厂模式主要分为以下几种类型:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

1.2 场景:操作不同类型的动物

我们假设有一个场景,程序需要对不同种类的动物进行操作,动物可以发出不同的声音。

1.2.1 不用工厂模式

1.2.1.1 分析

在这个例子中,客户端代码直接依赖于具体的动物类 ( Dog, Cat, Bird),这意味着如果我们添加新的动物类型或者更改现有的创建逻辑,必须修改客户端代码。这种实现方式耦合度较高,不符合开闭原则。

类图:

image.png
// 动物接口
interface Animal {
    void makeSound();
}
// 具体动物类:狗
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof");
    }
}
// 具体动物类:猫
class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}
// 具体动物类:鸟
class Bird implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Tweet");
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 客户端直接实例化
        Animal animal1 = new Dog();
        // 输出:Woof
        animal1.makeSound();

        Animal animal2 = new Cat();
        // 输出:Meow
        animal2.makeSound();

        Animal animal3 = new Bird();
        // 输出:Tweet
        animal3.makeSound();
    }
}

1.2.1.1 优缺点

  1. 优点:
  • 简单直接:客户端直接实例化对象,代码较为简单,适用于对象数量少、变动少的情况。
  1. 缺点:
  • 高耦合性:客户端依赖具体类,任何对象的变化(如新增类、修改类)都需要修改客户端代码,违反开闭原则。
  • 扩展性差:当新增或修改对象时,需要改动已有代码,且对不同条件的判断逻辑可能会扩散到多个地方。

1.2.2 简单工厂模式

简单工厂模式使用一个单独的类根据参数创建不同类型的对象。它是一种具体的工厂,不属于设计模式中的 23 种经典设计模式,但经常被用作学习的起点。

1.2.2.1 结构

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

1.2.2.2 分析

  • 在简单工厂模式中,AnimalFactory 类封装了对象的创建逻辑,客户端只需要传递参数来指定创建的动物类型,而无需知道具体的类。
  • 虽然解决了直接依赖具体类的问题,但如果我们想添加新的动物类型,仍需要修改 AnimalFactory 类的逻辑,这违反了开闭原则。

类图:

image.png
// 简单工厂类
class AnimalFactory {
    public Animal createAnimal(String type) {
        if ("Dog".equalsIgnoreCase(type)) {
            return new Dog();
        } else if ("Cat".equalsIgnoreCase(type)) {
            return new Cat();
        } else if ("Bird".equalsIgnoreCase(type)) {
            return new Bird();
        } else {
            throw new IllegalArgumentException("Unknown animal type");
        }
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        Animal animal1 = factory.createAnimal("Dog");
        // 输出:Woof
        animal1.makeSound();

        Animal animal2 = factory.createAnimal("Cat");
        // 输出:Meow
        animal2.makeSound();

        Animal animal3 = factory.createAnimal("Bird");
        // 输出:Tweet
        animal3.makeSound();
    }
}

1.2.1.3 优缺点

  1. 优点:
  • 创建逻辑集中:将对象的创建集中在一个工厂类中,客户端只需知道要创建的对象类型(传递字符串或参数),降低了对具体类的依赖。
  • 简化客户端代码:客户端不再负责具体对象的创建,只需调用工厂方法。
  1. 缺点:
  • 违反开闭原则:如果需要添加新的类型,需要修改工厂类的创建逻辑(if-elseswitch-case 语句)。
  • 复杂性增加:随着对象类型增多,工厂类的创建逻辑可能变得复杂,不利于维护。

1.2.1.4 扩展:静态工厂

在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的,这个就是静态工厂模式,它也不是 23 种设计模式中的。

类图:

image.png
// 静态工厂类
class AnimalFactory {
    public static Animal createAnimal(String type) {
        if ("Dog".equalsIgnoreCase(type)) {
            return new Dog();
        } else if ("Cat".equalsIgnoreCase(type)) {
            return new Cat();
        } else if ("Bird".equalsIgnoreCase(type)) {
            return new Bird();
        } else {
            throw new IllegalArgumentException("Unknown animal type");
        }
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        Animal animal1 = AnimalFactory.createAnimal("Dog");
        // 输出:Woof
        animal1.makeSound();

        Animal animal2 = AnimalFactory.createAnimal("Cat");
        // 输出:Meow
        animal2.makeSound();

        Animal animal3 = AnimalFactory.createAnimal("Bird");
        // 输出:Tweet
        animal3.makeSound();
    }
}

1.2.3 工厂方法模式

工厂方法模式定义了一个创建对象的接口,但让子类决定实例化哪个类。工厂方法模式将对象的创建推迟到子类。

1.2.3.1 结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。抽象工厂既可以是接口也可以是抽象类,具体使用哪种形式取决于具体的设计需求和场景。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

1.2.3.2 分析

  • 在工厂方法模式中,每个具体的动物都有一个对应的工厂类,工厂类负责创建对应的动物实例。
  • 这种模式遵循了开闭原则,添加新的动物类型只需新建一个工厂类和对应的动物类,而无需修改现有代码。

类图:

image.png
// 抽象工厂类
abstract class AnimalFactory {
    public abstract Animal createAnimal();
}
// 具体工厂类:狗工厂类
class DogFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}
// 具体工厂类:猫工厂类
class CatFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}
// 具体工厂类:鸟工厂类
class BirdFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Bird();
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        AnimalFactory factory1 = new DogFactory();
        Animal animal1 = factory1.createAnimal();
        // 输出:Woof
        animal1.makeSound();

        AnimalFactory factory2 = new CatFactory();
        Animal animal2 = factory2.createAnimal();
        // 输出:Meow
        animal2.makeSound();

        AnimalFactory factory3 = new BirdFactory();
        Animal animal3 = factory3.createAnimal();
        // 输出:Tweet
        animal3.makeSound();
    }
}

1.2.3.3 优缺点

  1. 优点:
  • 符合开闭原则:工厂方法模式通过新增具体工厂类来扩展产品类型,而不修改已有代码,符合开闭原则。
  • 解耦合:客户端不再依赖于具体类,而是依赖于抽象工厂接口,提升了代码的可扩展性和灵活性。
  • 职责分离:每个工厂负责创建一种产品,工厂类和产品类的职责更加明确,便于维护。
  1. 缺点:
  • 增加类的数量:每增加一种产品类型,都需要新建对应的工厂类,这会使类的数量增多,增加代码的复杂性。
  • 适用场景有限:适合有多个类型的产品且产品类型较稳定的场景。如果产品类型非常多,工厂方法模式可能显得冗余。

1.2.4 抽象工厂模式

抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。它通常用于需要创建多个相关产品的场景。

1.2.4.1 结构

抽象工厂模式的主要角色如下:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。抽象工厂既可以是接口也可以是抽象类,具体使用哪种形式取决于具体的设计需求和场景。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

1.2.4.2 分析

  • 在抽象工厂模式中,AnimalFactory 提供了创建动物和食物的接口。不同的具体工厂(DogFactoryCatFactoryBirdFactory)负责创建不同的动物及其食物。
  • 这种模式适合在需要创建相关产品族时使用,比如同一类的动物和它们的食物。在不修改已有工厂的情况下,可以扩展新的动物和食物种类。

类图:

image.png
// 食物接口
interface Food {
    void eat();
}
// 具体食物类:狗粮
class DogFood implements Food {
    @Override
    public void eat() {
        System.out.println("Dog is eating dog food.");
    }
}
// 具体食物类:猫粮
class CatFood implements Food {
    @Override
    public void eat() {
        System.out.println("Cat is eating cat food.");
    }
}
// 具体食物类:鸟粮
class BirdFood implements Food {
    @Override
    public void eat() {
        System.out.println("Bird is eating bird seeds.");
    }
}
// 抽象工厂类
interface AnimalFactory {
    Animal createAnimal();
    Food createFood();
}
// 具体工厂类:狗工厂类
class DogFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Dog();
    }

    @Override
    public Food createFood() {
        return new DogFood();
    }
}
// 具体工厂类:猫工厂类
class CatFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }

    @Override
    public Food createFood() {
        return new CatFood();
    }
}
// 具体工厂类:鸟工厂类
class BirdFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Bird();
    }

    @Override
    public Food createFood() {
        return new BirdFood();
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        AnimalFactory factory1 = new DogFactory();
        Animal animal1 = factory1.createAnimal();
        Food food1 = factory1.createFood();
        // 输出:Woof
        animal1.makeSound();
        // 输出:Dog is eating dog food.
        food1.eat();

        AnimalFactory factory2 = new CatFactory();
        Animal animal2 = factory2.createAnimal();
        Food food2 = factory2.createFood();
        // 输出:Meow
        animal2.makeSound();
        // 输出:Cat is eating cat food.
        food2.eat();

        AnimalFactory factory3 = new BirdFactory();
        Animal animal3 = factory3.createAnimal();
        Food food3 = factory3.createFood();
        // 输出:Tweet
        animal3.makeSound();
        // 输出:Bird is eating bird seeds.
        food3.eat();
    }
}

1.2.4.3 优缺点

  1. 优点:
  • 产品族管理:能够创建相关联的一系列产品(即产品族),适合创建一组相互依赖的对象,如某一类产品和它的配件。
  • 解耦产品族与客户端:客户端不关心产品的具体实现,而是通过抽象工厂统一获取产品,降低了代码的耦合度。
  • 符合开闭原则:可以通过扩展工厂来增加新的产品族,而不修改已有代码,符合开闭原则。
  1. 缺点:
  • 复杂度高:抽象工厂模式的结构复杂,增加了类和接口的数量,导致系统变得臃肿,尤其是在不需要创建产品族的情况下。
  • 扩展产品等级结构困难:虽然易于扩展产品族(增加一组新产品),但如果需要为已有的产品族增加新的产品等级结构(如在已有的产品类中再增加一个功能),需要修改所有的工厂接口和具体工厂类。

1.2.5 抽象工厂模式和工厂方法模式的区别与联系

抽象工厂模式工厂方法模式 的扩展。抽象工厂模式解决了 多个相关产品 一起创建的需求,而工厂方法模式只处理单一产品的创建

1.2.5.1 联系

  • 工厂方法模式:主要用于创建 单个产品。每个具体的工厂类负责创建一种具体的产品,工厂方法模式的重点是为某个类型的产品提供创建方法,客户端通过调用工厂接口来创建产品对象。

  • 抽象工厂模式:不仅仅创建单个产品,而是用于创建一系列相关的产品族。抽象工厂为不同的产品族提供接口,允许客户端使用不同的具体工厂来创建整个产品族中的所有产品,而不需要修改客户端代码。

1.2.5.2 不同点

  1. 产品的数量

    • 工厂方法模式:一个工厂类只创建一个产品
    • 抽象工厂模式:一个工厂类可以创建多个相关的产品(即产品族)。
  2. 复杂度

    • 工厂方法模式相对较简单,关注于单一产品的创建。
    • 抽象工厂模式更加复杂,适用于有多个产品需要同时创建,且这些产品通常是有内在关联的情况。

1.3 总结

  • 不用工厂模式:简单但耦合度高,扩展性差。
  • 简单工厂模式:将对象的创建逻辑集中管理,但扩展性差,违反开闭原则。
  • 工厂方法模式:符合开闭原则,增加扩展性,适合单个产品的创建,但类数量增多。
  • 抽象工厂模式:适合创建一组相关产品,能管理产品族,扩展性强,但实现复杂,增加了系统的难度。

1.4 通过 简单工厂模式+配置文件 解除耦合

通过简单工厂模式配置文件的结合,可以有效解除客户端和具体产品类之间的耦合。这种方式通过在配置文件中配置具体产品类的名称或类型,简单工厂读取配置文件动态创建对象,从而让客户端不需要直接依赖具体类。这样如果以后要替换或新增产品,客户端代码无需修改,只需要更新配置文件和相应的工厂逻辑。

1.4.1 步骤分析

  1. 配置文件:将需要创建的类(具体产品)的信息存储在配置文件中,工厂可以根据该配置文件动态加载类。
  2. 简单工厂模式:根据读取到的配置文件的内容,工厂通过反射等机制动态创建具体的产品对象。
  3. 解除耦合:客户端不再直接依赖具体的产品类,而是依赖工厂类。通过工厂类读取配置文件,灵活地创建不同的产品。

1.4.2 例子

类图:

image.png

配置文件 (config.properties):配置文件中指定了产品类的全限定类名,便于工厂动态读取和创建实例。

Dog=patterns.factory.Implementation.after.configfactory.Dog
Cat=patterns.factory.Implementation.after.configfactory.Cat
Bird=patterns.factory.Implementation.after.configfactory.Bird
// 简单工厂类+配置文件
class AnimalFactory {
    // 加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储
    private static HashMap<String, Animal> map = new HashMap<>();

    // 加载配置文件, 只需要加载一次
    static {
        // 根据配置文件创建产品对象
        Properties properties = new Properties();
        InputStream in = AnimalFactory.class.getClassLoader().getResourceAsStream("config.properties");

        try {
            properties.load(in);
            // 从配置文件对象中获取全类名并创建对象
            Set<Object> keys = properties.keySet();
            for (Object key : keys) {
                String className = properties.getProperty((String) key);
                // 通过反射技术创建对象
                Class<?> clazz = Class.forName(className);
                Animal animal = (Animal) clazz.getDeclaredConstructor().newInstance();
                // 将名称和对象存储到容器中
                map.put(((String) key).toLowerCase(), animal);
            }
            if (in != null) {
                in.close();
            }
        } catch (IOException | ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }

    public static Animal createAnimal(String type) {
        return map.get(type.toLowerCase());
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 客户端通过工厂获取具体产品,而不关心具体产品的实现
        Animal animal1 = AnimalFactory.createAnimal("Dog");
        // 输出:Woof
        animal1.makeSound();
        Animal animal2 = AnimalFactory.createAnimal("Cat");
        // 输出:Meow
        animal2.makeSound();
        Animal animal3 = AnimalFactory.createAnimal("Bird");
        // 输出:Tweet
        animal3.makeSound();
    }
}

1.4.3 关键点

  1. 配置文件:配置文件 config.properties 存储了具体类的类名信息,这样可以方便更改具体的实现。比如,修改配置文件中的 DogCat,就会创建 Cat 类的对象,而不需要修改客户端代码。

  2. 反射机制:工厂通过反射动态加载配置文件中的类名,并创建对应的实例。

  3. 解耦合:客户端不再依赖于具体的 DogCat 类,而是依赖于工厂,工厂通过配置文件灵活创建实例。即便以后新增其他 Animal 实现类,客户端也无需修改,只需调整配置文件。

1.4.4 优缺点

  1. 优点:
  • 低耦合:客户端不直接依赖具体产品,具体产品类可以灵活替换。
  • 扩展性强:通过修改配置文件即可动态替换不同的产品类,而不影响代码。
  • 维护性好:新增产品时,只需新增实现类和配置,而不需要修改客户端代码。
  1. 缺点:
  • 反射开销:使用反射机制会带来一定的性能开销,且在编译期无法检测类的有效性,容易在运行时出现错误。
  • 配置管理:需要额外的配置文件管理。

1.5 JDK源码解析-Collection.iterator方法

Collection.iterator() 方法的设计实际上可以看作是工厂模式的一个应用。虽然工厂模式在经典的形式中通常用于创建独立的对象,但在 Java 的集合框架中,iterator() 方法提供了类似工厂模式的功能:它通过接口返回一个 Iterator 对象,而不用暴露 Iterator 的具体实现,符合工厂模式的核心思想,即将对象的创建和使用分离

类图:

image.png

1.5.1 Iterator 和 Collection

Iterator 是 Java 集合框架中的一个接口,允许客户端在不知道集合内部实现的情况下进行遍历。Collection 是所有集合类的顶层接口,如 ListSetQueue 等都实现了这个接口。而 iterator() 方法则是 Collection 接口中的一个方法,它返回该集合元素的迭代器(Iterator),用于遍历集合。

1.5.2 如何体现工厂模式

工厂模式的核心思想是:

  • 提供一个接口,用于创建对象。
  • 隐藏具体实现,让客户端只关心接口,不关心具体实现。

iterator() 方法符合这种思路,它提供一个接口 Iterator 来遍历集合,而客户端并不需要关心具体集合类是如何实现 Iterator 的。

  • Collection 是集合的顶层接口,定义了 iterator() 方法。
  • Iterator 是迭代器的接口,定义了迭代器需要的方法,如 hasNext()next()remove()
  • ListSet 分别实现了 Collection 接口,提供了具体的 iterator() 实现。它们返回的是各自特定的迭代器。

1.5.4 工厂模式的体现

  • Collection 接口中的 iterator() 方法就像是一个工厂方法,返回 Iterator 对象。
  • 每个具体的集合类(如 ListSet)都提供了自己的 iterator() 实现。这相当于工厂方法中的不同工厂类,返回不同的产品对象(不同的 Iterator 实现)。
  • 客户端调用 iterator() 后,得到的是 Iterator 接口,而不是具体的 Iterator 实现类。这种方式屏蔽了集合内部的实现细节,客户端不需要关心集合的具体类型,只需要按照 Iterator 接口的规范来操作集合。
1.5.4.1 Collection 接口(简化版)
public interface Collection<E> {
    Iterator<E> iterator();
}
1.5.4.2 List 和 Set 类
public class Client {
    public static void main(String[] args) {
        // 使用ArrayList的迭代器
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        Iterator<String> listIterator = list.iterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }

        // 使用HashSet的迭代器
        HashSet<String> set = new HashSet<>();
        set.add("X");
        set.add("Y");
        set.add("Z");

        Iterator<String> setIterator = set.iterator();
        while (setIterator.hasNext()) {
            System.out.println(setIterator.next());
        }
    }
}

1.5.5 工厂模式的优缺点在 Collection.iterator() 中的体现

  1. 优点:
  • 解耦:客户端无需知道集合的具体实现,只需要通过 Iterator 接口来进行遍历。无论是 ListSet 还是其他集合类型,都提供统一的遍历方式。
  • 扩展性强:如果添加新的集合类型,只需要提供自己的 iterator() 实现即可,客户端不需要做任何修改。
  1. 缺点:
  • 工厂模式可能会导致类的数量增加,因为每种具体集合类型都需要提供自己的迭代器实现。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容