面向?qū)ο缶幊淘O(shè)計(jì)模式------工廠模式(簡單工廠隘截、工廠方法扎阶、抽象工廠)

1、簡單工廠模式

??簡單工廠模式又叫靜態(tài)工廠方法模式(Static Factory Method Pattern)婶芭,是通過專門定義一個(gè)類來負(fù)責(zé)創(chuàng)建其他類的實(shí)例东臀,被創(chuàng)建的實(shí)例通常都具有共同的父類。
??一個(gè)簡單的實(shí)例:要求實(shí)現(xiàn)一個(gè)計(jì)算機(jī)控制臺程序犀农,要求輸入數(shù)的運(yùn)算結(jié)果惰赋。最原始的解決方法如下:

/**
 * @Description:這里使用的是最基本的實(shí)現(xiàn),并沒有體現(xiàn)出面向?qū)ο蟮木幊趟枷牒巧冢a的擴(kuò)展性差赁濒,甚至連除數(shù)可能為0的情況也沒有考慮
 */
public static void main(String[] args) {
    scanner = new Scanner(System.in);
    
    System.out.print("請輸入第一個(gè)數(shù)字:");
    int firstNum = scanner.nextInt();
    
    System.out.print("請輸入第二個(gè)數(shù)字:");
    int secondNum = scanner.nextInt();
    
    System.out.print("請輸入運(yùn)算符:");
    String operation = scanner.next();
    
    if(operation.equals("+")) {
        System.out.println("result:" + (firstNum + secondNum));
    } else if(operation.equals("-")) {
        System.out.println("result:" + (firstNum - secondNum));
    } else if(operation.equals("*")) {
        System.out.println("result:" + (firstNum * secondNum));
    } else if(operation.equals("/")){
        System.out.println("result:" + (firstNum / secondNum));
    }
}

??上面的寫法實(shí)現(xiàn)雖然簡單,但是卻沒有面向?qū)ο蟮奶匦悦虾Γa拓展性差拒炎,甚至沒有考慮除數(shù)可能為0的特殊情況。
??在面向?qū)ο缶幊陶Z言中挨务,一切都是對象击你,所以上面運(yùn)算符號也應(yīng)當(dāng)作對象來處理。因此我們首先建立一個(gè)運(yùn)算接口谎柄,所有其他的運(yùn)算都封裝成類丁侄,并實(shí)現(xiàn)該運(yùn)算接口。

/**
 * @Description: 定義一個(gè)運(yùn)算接口朝巫,將所有的運(yùn)算符號都封裝成類鸿摇,并實(shí)現(xiàn)本接口
 * @author: zxt
 * @time: 2018年7月6日 上午10:24:13
 */
public interface Operation {
    public double getResult(double firstNum, double secondNum);
}

public class AddOperation implements Operation {
    @Override
    public double getResult(double firstNum, double secondNum) {
        return firstNum + secondNum;
    }
}

public class SubOperation implements Operation {
    @Override
    public double getResult(double firstNum, double secondNum) {
        return firstNum - secondNum;
    }
}

public class MulOperation implements Operation {
    @Override
    public double getResult(double firstNum, double secondNum) {
        return firstNum * secondNum;
    }
}

public class DivOperation implements Operation {
    @Override
    public double getResult(double firstNum, double secondNum) {
        if(secondNum == 0) {
            try {
                throw new Exception("除數(shù)不能為0!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        return firstNum / secondNum;
    }
}

??現(xiàn)在的問題的是劈猿,如何根據(jù)不同的情況創(chuàng)建不同的對象拙吉,這里就可以使用簡單工廠模式來實(shí)現(xiàn)了潮孽,客戶端只需要提供運(yùn)算符,工廠類會(huì)判斷并生成相應(yīng)的運(yùn)算類:

/**
 * @Description: 簡單工廠模式:通過一個(gè)工廠類庐镐,根據(jù)情況創(chuàng)建不同的對象
 * @author: zxt
 * @time: 2018年7月6日 上午10:50:15
 */
public class OperationFactory {
    /**
     * @Description:根據(jù)運(yùn)算符得到具體的運(yùn)算類
     * @param operationStr
     */
    public static Operation getOperation(String operationStr) {
        Operation result = null;
        
        switch(operationStr) {
        case "+":
            result = new AddOperation();
            break;
        case "-":
            result = new SubOperation();
            break;
        case "*":
            result = new MulOperation();
            break;
        case "/":
            result = new DivOperation();
            break;
        }
        
        return result;
    }
}

// 客戶端調(diào)用
Operation oper = OperationFactory.getOperation(operation);
double result = oper.getResult(firstNum, secondNum);
System.out.println(result);

??簡單工廠將對象的創(chuàng)建過程進(jìn)行了封裝恩商,用戶不需要知道具體的創(chuàng)建過程,只需要調(diào)用工廠類獲取對象即可必逆。
??這種簡單工廠的寫法是通過switch-case來判斷對象創(chuàng)建過程的怠堪。在實(shí)際使用過程中,違背了開放-關(guān)閉原則(例如名眉,當(dāng)需要擴(kuò)展一個(gè)新的運(yùn)算符之后粟矿,簡單工廠創(chuàng)建的對象也必須多一種,這就需要修改原來的代碼了损拢,違背了對修改關(guān)閉的原則)陌粹,當(dāng)然有些情況下可以通過反射調(diào)用來彌補(bǔ)這種不足。

2福压、工廠方法模式

??簡單工廠模式的最大優(yōu)點(diǎn)在于工廠類中包含了必要的邏輯判斷掏秩,根據(jù)客戶端的選擇條件動(dòng)態(tài)實(shí)例化相關(guān)的類,對于客戶端來說荆姆,去除了與具體產(chǎn)品的依賴蒙幻。但是每擴(kuò)展一個(gè)類時(shí),都需要改變工廠類里的方法胆筒,這就違背了開放-封閉原則邮破。于是工廠方法模式來了:
??工廠方法模式(Factory Method),定義一個(gè)用于創(chuàng)建對象的接口仆救,讓子類決定實(shí)例化哪一個(gè)類抒和,工廠方法使一個(gè)類的實(shí)例化延遲到其子類。 繼續(xù)上一個(gè)計(jì)算器的例子彤蔽,簡單工廠模式由工廠類直接生成相應(yīng)的運(yùn)算類對象摧莽,判斷的邏輯在工廠類中,而工廠方法模式的實(shí)現(xiàn)則是定義一個(gè)工廠接口顿痪,然后每個(gè)運(yùn)算類都對應(yīng)一個(gè)工廠類來創(chuàng)建镊辕,然后在客戶端判斷使用哪個(gè)工廠類來創(chuàng)建運(yùn)算類。

/**
 * @Description: 工廠的接口
 * @author: zxt
 * @time: 2019年2月21日 下午2:49:43
 */
public interface IFactory {
    
    public Operation createOperation();
}

/**
 * @Description: 加法類工廠
 */
public class AddFactory implements IFactory {
    @Override
    public AddOperation createOperation() {
        return new AddOperation();
    }
}

/**
 * @Description: 減法類工廠
 */
public class SubFactory implements IFactory {
    @Override
    public SubOperation createOperation() {
        return new SubOperation();
    }
}

/**
 * @Description: 乘法類工廠
 */
public class MulFactory implements IFactory {
    @Override
    public MulOperation createOperation() {
        return new MulOperation();
    }
}

/**
 * @Description: 除法類工廠
 */
public class DivFactory implements IFactory {

    @Override
    public DivOperation createOperation() {
        return new DivOperation();
    }
}

??工廠方法模式實(shí)現(xiàn)時(shí)员魏,客戶端需要決定實(shí)例化哪一個(gè)工廠來實(shí)現(xiàn)運(yùn)算類丑蛤,選擇判斷的問題還是存在的叠聋,也就是說撕阎,工廠方法把簡單工廠的內(nèi)部邏輯判斷移到了客戶端代碼來進(jìn)行。你想要加功能碌补,本來是改工廠類的虏束,而現(xiàn)在是修改客戶端棉饶。

/**
 * @Description: 實(shí)現(xiàn)一個(gè)簡單的計(jì)算器功能,使用工廠方法模式
 * @author: zxt
 * @time: 2018年7月6日 上午10:11:50
 */
public class Computer {

    private static Scanner scanner;
    
    public static void main(String[] args) {
        scanner = new Scanner(System.in);
        
        System.out.print("請輸入第一個(gè)數(shù)字:");
        int firstNum = scanner.nextInt();
        
        System.out.print("請輸入第二個(gè)數(shù)字:");
        int secondNum = scanner.nextInt();
        
        System.out.print("請輸入運(yùn)算符:");
        String operation = scanner.next();
        
        IFactory operFactory = null;
        if(operation.equals("+")) {
            operFactory = new AddFactory();
        } else if(operation.equals("-")) {
            operFactory = new SubFactory();
        } else if(operation.equals("*")) {
            operFactory = new MulFactory();
        } else if(operation.equals("/")){
            operFactory = new DivFactory();
        }
        Operation oper = operFactory.createOperation();
        double result = oper.getResult(firstNum, secondNum);
        System.out.println("result = " + result);
    }
}

??增加新功能時(shí)镇匀,工廠方法模式比簡單工廠模式修改的代碼量更小照藻,工廠方法克服了簡單工廠違背開放封閉原則的缺點(diǎn),又保持了封裝對象創(chuàng)建過程的優(yōu)點(diǎn)汗侵。但是工廠方法的缺點(diǎn)就是每加一個(gè)產(chǎn)品幸缕,就需要加一個(gè)產(chǎn)品工廠的類,增加了額外的開發(fā)量晰韵。當(dāng)然這兩種模式都還不是最佳的做法发乔。

3、抽象工廠模式

??抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)雪猪。抽象工廠模式是指當(dāng)有多個(gè)抽象角色時(shí)栏尚,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個(gè)接口只恨,使客戶端在不必指定產(chǎn)品的具體的情況下译仗,創(chuàng)建多個(gè)產(chǎn)品族中的產(chǎn)品對象。根據(jù)里氏替換原則官觅,任何接受父類型的地方纵菌,都應(yīng)當(dāng)能夠接受子類型。因此缰猴,實(shí)際上系統(tǒng)所需要的产艾,僅僅是類型與這些抽象產(chǎn)品角色相同的一些實(shí)例,而不是這些抽象產(chǎn)品的實(shí)例滑绒。換言之闷堡,也就是這些抽象產(chǎn)品的具體子類的實(shí)例。工廠類負(fù)責(zé)創(chuàng)建抽象產(chǎn)品的具體子類的實(shí)例疑故。
??抽象工廠模式(Abstract Factory):提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對象的接口杠览,而無需指定他們具體的類。
??實(shí)例場景:對數(shù)據(jù)庫(各種不同的數(shù)據(jù)庫)中的表進(jìn)行修改纵势,此時(shí)踱阿,使用工廠模式結(jié)構(gòu)圖如下:

1、User表的定義:

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2钦铁、定義一個(gè)對User表進(jìn)行操作的接口:

/**
 * @Description: 對User類操作的接口
 * @author: zxt
 * @time: 2019年2月24日 下午7:00:20
 */
public interface IUser {
    
    void insert(User user);
    
    User getUser(int id);
}

3软舌、實(shí)現(xiàn)Sql Server數(shù)據(jù)庫對User表的操作:

/**
 * @Description:  SQL Server數(shù)據(jù)庫中對User表的操作
 * @author: zxt
 * @time: 2019年2月24日 下午7:04:39
 */
public class SqlServerUser implements IUser {
    @Override
    public void insert(User user) {
        System.out.println("在  SQL Server 中給 User 表增加一條記錄!");
    }

    @Override
    public User getUser(int id) {
        System.out.println("在  SQL Server 中根據(jù)ID得到  User 表的一條記錄牛曹!");
        return null;
    }
}

實(shí)現(xiàn)Oracle數(shù)據(jù)庫對User表的操作:

/**
 * @Description: Oracle數(shù)據(jù)庫中對User表的操作
 * @author: zxt
 * @time: 2019年2月24日 下午7:05:07
 */
public class OracleUser implements IUser {

    @Override
    public void insert(User user) {
        System.out.println("在  Oracle 中給 User 表增加一條記錄佛点!");
    }

    @Override
    public User getUser(int id) {
        System.out.println("在 Oracle 中根據(jù)ID得到  User 表的一條記錄!");
        return null;
    }
}

4、定義一個(gè)抽象工廠接口超营,用于生成對User表的操作的對象:

/**
 * @Description: 得到對User表操作的IUser對象的抽象工廠接口
 * @author: zxt
 * @time: 2019年2月24日 下午7:06:37
 */
public interface IFactory {
    
    public IUser createUser();
}

5鸳玩、SQLServerFactory工廠用于生成操作Sql Server數(shù)據(jù)庫的SqlServerUser對象:

public class SQLServerFactory implements IFactory {

    @Override
    public IUser createUser() {
        return new SqlServerUser();
    }
}

OracleFactory工廠用于生成操作Oracle數(shù)據(jù)庫的OracleUser對象:

public class OracleFactory implements IFactory {

    @Override
    public IUser createUser() {
        return new OracleUser();
    }
}

6、客戶端的使用:

public class FactoryMethodTest {

    public static void main(String[] args) {
        User user = new User();
        
        // 若要改成Oracle數(shù)據(jù)庫演闭,只需要將這句改成OracleFactory即可
        IFactory ifactory = new SQLServerFactory();
        
        IUser iu = ifactory.createUser();
        
        iu.insert(user);
        iu.getUser(1);
    }
}


??到此為止不跟,工廠模式都可以很好的解決,由于多態(tài)的關(guān)系米碰,IFactory在聲明對象之前都不知道在訪問哪個(gè)數(shù)據(jù)庫窝革,卻可以在運(yùn)行時(shí)很好的完成任務(wù),這就是業(yè)務(wù)邏輯與數(shù)據(jù)訪問的解耦吕座。
??但是聊闯,當(dāng)數(shù)據(jù)庫中不止一個(gè)表的時(shí)候該怎么解決問題呢,此時(shí)就可以引入抽象工廠模式了米诉,結(jié)構(gòu)圖如下:


例如增加了部門表Department:

public class Department {
    private int id;
    private String deptName;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
}

則增加相應(yīng)的對Department表操作的接口:

public interface IDepartment {
    
    public void insert(Department department);
    
    public Department getDepartment(int id);
}

實(shí)現(xiàn)Sql Server數(shù)據(jù)庫對Department表的操作:

/**
 * @Description:  SQL Server數(shù)據(jù)庫中對Department表的操作
 * @author: zxt
 * @time: 2019年2月24日 下午7:04:39
 */
public class SqlServerDepartment implements IDepartment {
    @Override
    public void insert(Department user) {
        System.out.println("在  SQL Server 中給 Department 表增加一條記錄菱蔬!");
    }

    @Override
    public Department getDepartment(int id) {
        System.out.println("在  SQL Server 中根據(jù)ID得到  Department 表的一條記錄!");
        return null;
    }
}

實(shí)現(xiàn)Oracle數(shù)據(jù)庫對Department表的操作:

/**
 * @Description: Oracle數(shù)據(jù)庫中對Department表的操作
 * @author: zxt
 * @time: 2019年2月24日 下午7:05:07
 */
public class OracleDepartment implements IDepartment {
    @Override
    public void insert(Department user) {
        System.out.println("在  Oracle 中給 Department 表增加一條記錄史侣!");
    }

    @Override
    public Department getDepartment(int id) {
        System.out.println("在 Oracle 中根據(jù)ID得到  Department 表的一條記錄拴泌!");
        return null;
    }
}

IFactory抽象工廠中增加生成對Department表操作的對象:

/**
 * @Description: 得到對User表操作的IUser對象的抽象工廠接口
 * @author: zxt
 * @time: 2019年2月24日 下午7:06:37
 */
public interface IFactory {
    
    public IUser createUser();
    
    public IDepartment createDepartment();
}

SQLServerFactory工廠增加生成操作Sql Server數(shù)據(jù)庫的SqlServerDepartment對象:

public class SQLServerFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new SqlServerUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new SqlServerDepartment();
    }
}

OracleFactory工廠增加生成操作Oracle數(shù)據(jù)庫的OracleDepartment對象:

public class OracleFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new OracleUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new OracleDepartment();
    }
}

客戶端的使用:

public class AbstractFactoryTest {

    public static void main(String[] args) {
        User user = new User();
        Department department = new Department();
        
        // 若要改成SQL Server數(shù)據(jù)庫,只需要將這句改成SqlServerFactory即可
        IFactory ifactory = new OracleFactory();
        
        IUser iu = ifactory.createUser();
        iu.insert(user);
        iu.getUser(1);
        
        IDepartment id = ifactory.createDepartment();
        id.insert(department);
        id.getDepartment(1);
    }
}



??所以抽象工廠與工廠方法模式的區(qū)別在于:抽象工廠是可以生產(chǎn)多個(gè)產(chǎn)品的惊橱,例如OracleFactory 里可以生產(chǎn) OracleUser以及 OracleDepartment兩個(gè)產(chǎn)品蚪腐,而這兩個(gè)產(chǎn)品又是屬于一個(gè)系列的,因?yàn)樗鼈兌际菍儆贠racle數(shù)據(jù)庫的表税朴。而工廠方法模式則只能生產(chǎn)一個(gè)產(chǎn)品回季,例如之前的 OracleFactory里就只可以生產(chǎn)一個(gè) OracleUser產(chǎn)品。


??抽象工廠模式的優(yōu)缺點(diǎn):
??優(yōu)點(diǎn):
??1正林、抽象工廠模式最大的好處是易于交換產(chǎn)品系列泡一,由于具體工廠類,例如 IFactory factory = new OracleFactory(); 在一個(gè)應(yīng)用中只需要在初始化的時(shí)候出現(xiàn)一次觅廓,這就使得改變一個(gè)應(yīng)用的具體工廠變得非常容易鼻忠,它只需要改變具體工廠即可使用不同的產(chǎn)品配置。不管是任何人的設(shè)計(jì)都無法去完全防止需求的更改杈绸,或者項(xiàng)目的維護(hù)帖蔓,那么我們的理想便是讓改動(dòng)變得最小、最容易瞳脓。
??2塑娇、抽象工廠模式的另一個(gè)好處就是它讓具體的創(chuàng)建實(shí)例過程與客戶端分離,客戶端是通過它們的抽象接口操作實(shí)例劫侧,產(chǎn)品實(shí)現(xiàn)類的具體類名也被具體的工廠實(shí)現(xiàn)類分離埋酬,不會(huì)出現(xiàn)在客戶端代碼中。就像我們上面的例子,客戶端只認(rèn)識IUser和IDepartment奇瘦,至于它是Sql Server里的表還是Oracle里的表就不知道了。
??缺點(diǎn):
??1劲弦、如果你的需求來自增加功能耳标,比如增加Department表,就有點(diǎn)太煩了邑跪。首先需要增加IDepartment次坡,SQLServerDepartment,OracleDepartment画畅。然后我們還要去修改工廠類:IFactory砸琅,SQLServerFactory,OracleFactory才可以實(shí)現(xiàn)轴踱,需要修改三個(gè)類症脂,實(shí)在是有點(diǎn)麻煩。
??2淫僻、還有就是诱篷,客戶端程序肯定不止一個(gè),每次都需要聲明IFactory factory = new OracleFactory()雳灵,如果有100個(gè)調(diào)用數(shù)據(jù)庫的類棕所,就需要更改100次IFactory factory = new OracleFactory()。

3.1悯辙、抽象工廠模式的改進(jìn)1(簡單工廠+抽象工廠)

??我們將IFactory琳省,SQLServerFactory,OracleFactory三個(gè)工廠類都拋棄掉躲撰,取而代之的是一個(gè)簡單工廠類EasyFactory针贬,如下:

public class EasyFactory {

    private static String db = "SqlServer";
    // private static String db = "Oracle";

    public static IUser createUser() {
        IUser result = null;
        switch (db) {
        case "SqlServer":
            result = new SqlServerUser();
            break;
        case "Oracle":
            result = new OracleUser();
            break;
        }

        return result;
    }

    public static IDepartment createDepartment() {
        IDepartment result = null;
        switch (db) {
        case "SqlServer":
            result = new SqlServerDepartment();
            break;
        case "Oracle":
            result = new OracleDepartment();
            break;
        }

        return result;
    }
}

客戶端:

public class EasyClient {

    public static void main(String[] args) {
        User user = new User();
        Department department = new Department();

        // 直接得到實(shí)際的數(shù)據(jù)庫訪問實(shí)例,而不存在任何依賴
        IUser userOperation = EasyFactory.createUser();

        userOperation.getUser(1);
        userOperation.insert(user);

        // 直接得到實(shí)際的數(shù)據(jù)庫訪問實(shí)例拢蛋,而不存在任何依賴
        IDepartment departmentOperation = EasyFactory.createDepartment();

        departmentOperation.insert(department);
        departmentOperation.getDepartment(1);
    }
}

??由于事先在簡單工廠類里設(shè)置好了db的值坚踩,所以簡單工廠的方法都不需要由客戶端來輸入?yún)?shù),這樣在客戶端就只需要使用 EasyFactory.createUser(); 和 EasyFactory.createDepartment(); 方法來獲得具體的數(shù)據(jù)庫訪問類的實(shí)例瓤狐,客戶端代碼上沒有出現(xiàn)任何一個(gè) SqlServer 或 Oracle 的字樣瞬铸,達(dá)到了解耦的目的,客戶端已經(jīng)不再受改動(dòng)數(shù)據(jù)庫訪問的影響了础锐。

3.2嗓节、抽象工廠的改進(jìn)2(反射+簡單工廠)

??使用反射的話,我們就可以不需要使用switch皆警,因?yàn)槭褂胹witch的話拦宣,我添加一個(gè)Mysql數(shù)據(jù)庫的話,又要switch的話又需要添加case條件。
??我們可以根據(jù)選擇的數(shù)據(jù)庫名稱鸵隧,如“mysql”绸罗,利用反射技術(shù)自動(dòng)的獲得所需要的實(shí)例:

public class EasyFactoryReflect {

    private static String packName = "com.zxt.abstractfactory";
    private static String sqlName = "Oracle";

    public static IUser createUser() throws Exception {
        String className = packName + "." + sqlName + "User";
        return (IUser) Class.forName(className).newInstance();
    }

    public static IDepartment createLogin() throws Exception {
        String className = packName + "." + sqlName + "Department";
        return (IDepartment) Class.forName(className).newInstance();
    }
}

??以上我們使用簡單工廠模式設(shè)計(jì)的代碼中,是用一個(gè)字符串類型的db變量來存儲(chǔ)數(shù)據(jù)庫名稱的豆瘫,所以變量的值到底是 SqlServer 還是 Oracle珊蟀,完全可以由事先設(shè)置的那個(gè)db變量來決定,而我們又可以通過反射來去獲取實(shí)例外驱,這樣就可以去除switch語句了育灸。

3.3、抽象工廠的改進(jìn)3(反射+配置文件+簡單工廠)

??在使用反射之后昵宇,我們還是需要進(jìn)EasyFactory中修改數(shù)據(jù)庫類型磅崭,還不是完全符合開-閉原則。我們可以通過配置文件來達(dá)到目的瓦哎,每次通過讀取配置文件來知道我們應(yīng)該使用哪種數(shù)據(jù)庫砸喻。
??如下是一個(gè)json類型的配置文件,也可以使用xml類型的配置文件:

{
    "packName": " com.zxt.abstractfactory",
    "DB": "Oracle"
}

??之后就可以通過這個(gè)配置文件去找需要加載的類是哪一個(gè)蒋譬。我們通過反射機(jī)制+配置文件+簡單工廠模式解決了數(shù)據(jù)庫訪問時(shí)的可維護(hù)恩够、可擴(kuò)展的問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羡铲,一起剝皮案震驚了整個(gè)濱河市蜂桶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌也切,老刑警劉巖扑媚,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雷恃,居然都是意外死亡疆股,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門倒槐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旬痹,“玉大人,你說我怎么就攤上這事讨越×讲校” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵把跨,是天一觀的道長人弓。 經(jīng)常有香客問我,道長着逐,這世上最難降的妖魔是什么崔赌? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任意蛀,我火速辦了婚禮,結(jié)果婚禮上健芭,老公的妹妹穿的比我還像新娘县钥。我一直安慰自己,他們只是感情好慈迈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布若贮。 她就那樣靜靜地躺著,像睡著了一般吩翻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锥咸,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天狭瞎,我揣著相機(jī)與錄音,去河邊找鬼搏予。 笑死熊锭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雪侥。 我是一名探鬼主播碗殷,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼速缨!你這毒婦竟也來了锌妻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旬牲,失蹤者是張志新(化名)和其女友劉穎仿粹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體原茅,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吭历,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了擂橘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晌区。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖通贞,靈堂內(nèi)的尸體忽然破棺而出朗若,到底是詐尸還是另有隱情,我是刑警寧澤昌罩,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布捡偏,位于F島的核電站,受9級特大地震影響峡迷,放射性物質(zhì)發(fā)生泄漏银伟。R本人自食惡果不足惜你虹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望彤避。 院中可真熱鬧傅物,春花似錦、人聲如沸琉预。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圆米。三九已至卒暂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娄帖,已是汗流浹背也祠。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留近速,地道東北人诈嘿。 一個(gè)月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓顿仇,卻偏偏與公主長得像惭等,于是被迫代替她去往敵國和親坦康。 傳聞我的和親對象是個(gè)殘疾皇子司光,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

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

  • 設(shè)計(jì)模式匯總 一思犁、基礎(chǔ)知識 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用厨钻、多...
    MinoyJet閱讀 3,947評論 1 15
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,970評論 6 13
  • 設(shè)計(jì)模式基本原則 開放-封閉原則(OCP)高每,是說軟件實(shí)體(類松邪、模塊首繁、函數(shù)等等)應(yīng)該可以拓展李滴,但是不可修改。開-閉原...
    西山薄涼閱讀 3,798評論 3 14
  • 鏈接:https://github.com/WiKi123/DesignPattern作者: WiKi123(gi...
    樹懶啊樹懶閱讀 3,517評論 0 2
  • 不記得有多久沒去過清吧酒吧活動(dòng)了蛮瞄,今晚去聽歌的時(shí)候所坯,有一種找回了年輕的記憶感覺,也曾經(jīng)跟好友定期去玩挂捅,那時(shí)感覺無憂...
    圓圓_04b9閱讀 229評論 0 0