JavaScript - 設(shè)計模式 - 命名空間


本小節(jié)主要講解三種常用的設(shè)計模式和命名空間,第一種是工廠模式,第二種是單利模式,第三種是觀察者模式


設(shè)計模式概述

是為了解決在開發(fā)中可能遇到的需求(相似),而提出的一套解決方法.

設(shè)計模式要求:

  • 在開發(fā)中整個系統(tǒng)需要一套設(shè)計模式(架構(gòu)師)
  • 來源:建筑(建房子)領(lǐng)域
  • 設(shè)計模式的四人幫: Erich Gamma翩瓜、Richard Helm审姓、Ralph Johnson 和 John Vlissides
  • 設(shè)計模式:總共有23種.
  • **設(shè)計模式類型:單利(例)模式≈嗨浮|觀察者模式⊥寄亍| 代理模式【翰|工廠模式≌⒆颉|適配器模式〗戎|橋接模式 | .... **
  • 設(shè)計模式的書:<設(shè)計模式><大話設(shè)計模式|大話數(shù)據(jù)結(jié)構(gòu)><23種常見的設(shè)計模式>

工廠模式

批量創(chuàng)建大量的同類型的對象

優(yōu)點(diǎn) :

  • 可以通過統(tǒng)一的借口來創(chuàng)建對象,根據(jù)傳入的參數(shù)不同來創(chuàng)建不同的對象,易于擴(kuò)展和維護(hù),穩(wěn)定性更好

核心過程 :

  • 提供一個父構(gòu)造函數(shù)
  • 設(shè)置這個父構(gòu)造函數(shù)的原型對象(屬性|方法)
  • 在父構(gòu)造函數(shù)身上添加靜態(tài)工廠方法

1.需要接收傳入的參數(shù)(要生產(chǎn)的產(chǎn)品的類型)
2.判斷 是否支持生產(chǎn)
3.設(shè)置子構(gòu)造函數(shù)的原型對象
4.把新創(chuàng)建的對象返回

  • 定制合作伙伴

  • 直接使用父構(gòu)造函數(shù)的靜態(tài)工廠方法來創(chuàng)建指定的產(chǎn)品對象

  • 示例代碼 :

<script>
    //1. 提供一個父構(gòu)造函數(shù)
    function PhoneMake(){};
    //2. 設(shè)置這個父構(gòu)造函數(shù)的原型對象(屬性|方法)
    PhoneMake.prototype.logDes = function(){
        console.log("我們的口號是:" + this.des);
    }

    //3. 在父構(gòu)造函數(shù)身上添加靜態(tài)工廠方法
    PhoneMake.factory = function(typeStr){
        // 3.1 需要接收傳入的參數(shù)(要生產(chǎn)的產(chǎn)品的類型)
        var productType =  typeStr;

        //var Dog = PhoneMake[productType];
        //3.2 判斷 是否支持生產(chǎn)
        if (typeof PhoneMake[productType]  != "function")
        {
            //拋出一個異常
            throw "對不起,我們工廠和這個品牌沒有商務(wù)合作,不能生產(chǎn)!"
        }

        //3.3 設(shè)置子構(gòu)造函數(shù)的原型對象
         //為了獲得構(gòu)造函數(shù)原型對象的方法
        PhoneMake[productType].prototype = new PhoneMake(); 

        //3.4 設(shè)置子構(gòu)造函數(shù)的原型對象
       var newProduct = new PhoneMake[productType]();

        //3.5 把新創(chuàng)建的對象返回
        return newProduct;
    }

    //4. 定制合作伙伴
    PhoneMake.iphone = function(){
        this.des = "最安全最穩(wěn)定的系統(tǒng),最垃圾的體驗(yàn)"
    }
    PhoneMake.oppo = function(){
        this.des = "充電兩小時,通話五分鐘"
    }
    PhoneMake.vivo = function(){
        this.des = "照亮你的美,你本來就很美"
    }
    PhoneMake.meizu = function(){
        this.des = "我就是我,不一樣的魅族"
    }

    //5. 直接使用父構(gòu)造函數(shù)的靜態(tài)工廠方法來創(chuàng)建指定的產(chǎn)品對象
    var iphone = PhoneMake.factory("iphone");
    var vivo = PhoneMake.factory("vivo");
    var oppo = PhoneMake.factory("oppo");
    var meizu = PhoneMake.factory("meizu");
    var xiaomi = PhoneMake.factory("xiaomi");

    iphone.logDes();
    vivo.logDes();
    oppo.logDes();
    meizu.logDes();

</script>

單利模式

在整個程序的運(yùn)行過程中,一個類只有一個實(shí)例對象

js中的單利模式

  • js沒有類(ES6才有的) ,js實(shí)現(xiàn)單利模式(限定討論的范圍)

1.字面量
2.內(nèi)置構(gòu)造函數(shù)(Array Date Function Object)
3.工廠函數(shù)
4.自定義構(gòu)造函數(shù)(單利模式)

  • js是什么樣的語言

1.弱類型,腳本,輕量級,面向?qū)ο?基于原型(對象),解釋行語言.函數(shù)式.
2.js到底是不是一門面向?qū)ο?類)的語言?
3.js是一門支持面向?qū)ο蟮恼Z言.(封裝|繼承|多態(tài))

單利模式實(shí)現(xiàn)之后的表現(xiàn)

var p1 = new 構(gòu)造函數(shù)()
var p2 = new 構(gòu)造函數(shù)()
p1 == p2

  • 示例代碼 :
<script>
    function Person(){
        //首先創(chuàng)建一個空的對象
        //默認(rèn)把新的對象賦值給this
        //把新對象返回
    }
    var p1 = new Person();
    var p2 = new Person();
    console.log(p1 == p2);
</script>

單利模式的實(shí)現(xiàn)方式01 ----> 全局變量

全局變量來保存對象實(shí)現(xiàn)單利模式

  • 提供一個全局的變量
  • 提供一個構(gòu)造函數(shù)Person
  • 在構(gòu)造函數(shù)內(nèi)部先判斷全局變量是否有值,如果有那么就直接返回
  • 如果沒有,那么就把this賦值給全局變量
  • 通過this設(shè)置屬性和方法

存在的問題

  • 使用一個全局變量來保存單利對象,該全局變量在整個作用域中都可以被訪問或者是修改,可能會輕易的被覆蓋或者是修改.

  • 修改之后,創(chuàng)建出來的實(shí)例對象就不再是之前的那個單利對象了.

  • 示例代碼 :

<script>
    var instance;
    function Person(){
        if(instance)
        {
            console.log("對象已經(jīng)被創(chuàng)建,直接把之前創(chuàng)建好的對象返回");
            return instance;
        }
        instance = this;
        this.name = "奧特曼";
        this.age = 1000;
        console.log("第一次創(chuàng)建對象,創(chuàng)建對象之后并返回");
    }

    var p1 = new Person();
    var p2 = new Person();
    console.log(p1 == p2);
    var p3 = new Person();

    instance = "demo";
    var p4 = new Person();
    console.log(p4);
    console.log(p4 == p1);
</script>

單利模式的實(shí)現(xiàn)方式02 ----> 靜態(tài)屬性

靜態(tài)成員:直接添加到構(gòu)造函數(shù)身上的屬性或者是方法

存在的問題

  • 構(gòu)造函數(shù)的靜態(tài)屬性其實(shí)也可能被修改,因此這種方法也不安全

  • 示例代碼 :

<script>
    function Person(){
        //判斷對象是否已經(jīng)被創(chuàng)建
        if (Person.instance)
        {
            console.log("之前已經(jīng)創(chuàng)建過對象,直接返回");
            return Person.instance;
        }

        this.name = "大黃蜂"
        Person.instance  = this;
        console.log("第一次創(chuàng)建");
    }

    var p1 = new Person();
    var p2 = new Person();
    console.log(p1 == p2);


    instance = "demo";
    var p3 = new Person();
    console.log(p1 == p3);

    Person.instance = "123";
    var p4 = new Person();
    console.log(p4 == p1);
</script>

單利模式的實(shí)現(xiàn)方式03 ----> 惰性函數(shù)

核心過程

  • 提供一個構(gòu)造函數(shù)

  • 在構(gòu)造函數(shù)內(nèi)部聲明一個私有的變量

  • 使用惰性函數(shù)定義更新構(gòu)造函數(shù)的實(shí)現(xiàn)(直接把instance返回)

  • 設(shè)置原型對象[新構(gòu)造函數(shù)的原型對象 = 舊構(gòu)造函數(shù)的原型對象]
    構(gòu)造函數(shù),prototype == 對象.proto

  • 使用新的構(gòu)造函數(shù)創(chuàng)建實(shí)例對象,并且賦值給instance

  • 修正對象的構(gòu)造函數(shù)指向

  • 通過instance設(shè)置實(shí)例屬性和方法

  • 示例代碼 :

<script>
    // 01 提供一個構(gòu)造函數(shù)
    function Person(){
        //this01
        //02 在構(gòu)造函數(shù)內(nèi)部聲明一個私有的變量
        var instance;
        //03 使用惰性函數(shù)定義更新構(gòu)造函數(shù)的實(shí)現(xiàn)(直接把instance返回)
        Person = function(){
            //內(nèi)部默認(rèn)會創(chuàng)建一個空的對象 this02
            return instance;
        }
        //04 設(shè)置原型對象[新構(gòu)造函數(shù)的原型對象 = 舊構(gòu)造函數(shù)的原型對象]
        //原型鏈繼承:Man.prototype = new Person();
        //原型式繼承:Man.prototype = Person.prototype;
        //Person.prototype = this.__proto__;  //非標(biāo)準(zhǔn)(代碼中不要出現(xiàn))
        Person.prototype = this;

        //05 使用新的構(gòu)造函數(shù)創(chuàng)建實(shí)例對象,并且賦值給instance
        instance = new Person();
        //instance = this;
        //06 修正對象的構(gòu)造函數(shù)指向
        instance.constructor = Person;
        // 07 通過instance設(shè)置實(shí)例屬性和方法
        instance.name = "我很好聽";
        // 08 把instance返回
        return instance;
    }

    Person.prototype.des = "描述信息";
    var p1 = new Person();
    Person.prototype.hi = "hi";

    var p2 = new Person();
    console.log(p1 == p2);

    console.log(p1.constructor == Person);  //true
    console.log(p1.des);
    console.log(p1.hi);
</script>

單利模式的實(shí)現(xiàn)方式04 ----> 全局變量 + 即時函數(shù)

  • 示例代碼 :
<script>
    var Person;
    (function(){
        var instance;

        Person = function (){
            if(instance)
            {
                return instance;
            }
            this.name = "momo";
            instance = this;
        }
    })();

    var p1 = new Person();
    var p2 = new Person();
    console.log(p1 == p2);
</script>

觀察者模式

觀察者模式舉例說明

  • 男生A和男生B同時都喜歡女生C,他們想時時監(jiān)視女生C的動向,動態(tài),所以他們找了女生C的閨蜜作為觀察者幫他們監(jiān)視實(shí)時動態(tài).這樣不管女生C有什么最新的動態(tài)都會被男生A和男生B監(jiān)聽到,開發(fā)中就是男生多了點(diǎn),動態(tài)多了點(diǎn),核心內(nèi)容就是這樣

  • 要求:

女神:rose(發(fā)布者)
男生:jack(訂閱者)
男生:tom(訂閱者)

  • 過程:

創(chuàng)建或者是設(shè)置一個發(fā)布者
創(chuàng)建訂閱者對象
注冊訂閱者
測試(發(fā)狀態(tài))

  • 示例代碼1 : 一個發(fā)布者,兩個訂閱者,關(guān)注的是一個狀態(tài)
<script>
    //01 創(chuàng)建或者是設(shè)置一個發(fā)布者
    var rose = {
        user:[],
        addUser:function(fn){
            if (typeof fn != "function")
            {
                throw "不支持該操作!";
            }
            this.user.push(fn);
        },
        removeUser:function(fn){
            for (var i = 0; i < this.user.length; i++) {
                if(this.user[i] == fn)
                {
                    console.log(fn + "取消了訂閱");
                    this.user.splice(i,1);
                }
            }
        },
        eat:function(){
            for (var i = 0; i < this.user.length; i++) {
               this.user[i]();
            }
        }
    }


    // 02 創(chuàng)建訂閱者對象
    var jack = {
        eat_jack:function(){
            console.log("我陪你去吃拉面吧  ---jack");
        }
    }
    var tom = {
        eat_tom:function(){
            console.log("我陪你去吃壽司吧  ---tom");
        }
    }

    // 03 注冊訂閱者
    rose.addUser(jack.eat_jack);
    rose.addUser(tom.eat_tom);

    //04 發(fā)布者狀態(tài)改變
    rose.eat();
    rose.removeUser(jack.eat_jack);
    rose.eat();
</script>
  • 示例代碼2 : 多個狀態(tài)
<script>
    //01 創(chuàng)建或者是設(shè)置一個發(fā)布者
    var publisher = {
        addUser:function(fn,type){
            var type = type || "eat";
            if (typeof fn != "function")
            {
                throw "不支持該操作!";
            }
            this.user[type].push(fn);
        },
        removeUser:function(fn,type){
            var type = type || "eat";
            for (var i = 0; i < this.user[type].length; i++) {
                if(this.user[type][i] == fn)
                {
                    console.log(fn + "取消了訂閱");
                    this.user[type].splice(i,1);
                }
            }
        },
        eat:function(){
            for (var i = 0; i < this.user["eat"].length; i++) {
               this.user["eat"][i]();
            }
        },
        sleep:function(){
            for (var i = 0; i < this.user["sleep"].length; i++) {
                //console.log(this.user,"++++");
                this.user["sleep"][i]();
            }
        }
    }

    var rose = {};
    //封裝一個函數(shù)用來快速的讓某個指定對象成為發(fā)布者
    function makePublisher(o){
        for(var i in publisher)
        {
            if (publisher.hasOwnProperty(i) && typeof publisher[i] == "function" ){
                o[i] = publisher[i];
            }
        }
        o.user = {
            eat:[],
            sleep:[]
        };
    }
    makePublisher(rose);

    // 02 創(chuàng)建訂閱者對象
    var jack = {
        eat_jack:function(){
            console.log("我陪你去吃拉面吧  ---jack");
        },
        sleep_jack:function(){
            console.log("晚安 rose  ---jack");
        }
    }

    // 03 注冊訂閱者
    rose.addUser(jack.eat_jack,"eat");        //關(guān)注rose肚子餓不餓
    rose.addUser(jack.sleep_jack,"sleep");     //關(guān)注rose困不困

    rose.eat();
    rose.sleep();
  • 示例代碼3 : 通用性處理
<script>
    //01 創(chuàng)建或者是設(shè)置一個發(fā)布者
    var publisher = {
        addUser:function(fn,type){
            var type = type || "eat";
            if (this.user[type] == undefined)
            {
                this.user[type] = [];
            }
            if (typeof fn != "function")
            {
                throw "不支持該操作!";
            }
            this.user[type].push(fn);
        },
        removeUser:function(fn,type){
            this.publish(type,fn);
        },
        publish:function(type,fn){
            var type = type || "eat";
            for (var i = 0; i < this.user[type].length; i++) {
                //判斷當(dāng)前是要取消訂閱還是要發(fā)布狀態(tài)
                if (typeof fn == "function")
                {
                    if(this.user[type][i] == fn)
                    {
                        console.log(fn + "取消了訂閱");
                        this.user[type].splice(i,1);
                    }
                }else
                {
                    this.user[type][i]();
                }

            }
        }
    }
    var rose = {
        eat:function(){
            this.publish("eat");
        },
        sleep:function(){
            this.publish("sleep");
        },
        read:function(){
            this.publish("read");
        }
    };
    function makePublisher(o){
        for(var i in publisher)
        {
            if (publisher.hasOwnProperty(i) && typeof publisher[i] == "function" ){
                o[i] = publisher[i];
            }
        }
        o.user = {
            eat:[],
            sleep:[]
        };
    }
    makePublisher(rose);

    var jack = {
        eat_jack:function(){
            console.log("我陪你去吃拉面吧  ---jack");
        },
        sleep_jack:function(){
            console.log("晚安 rose  ---jack");
        }
    }
    var tom = {
        eat_tom:function(){
            console.log("我買給你吧  ---tom");
        },
        sleep_tom:function(){
            console.log("今晚的太陽很好看 ---tom");
        },
        read_tom:function(){
            console.log("你也在學(xué)習(xí)js嗎?");
        }
    }

    rose.addUser(jack.eat_jack,"eat");
    rose.addUser(tom.sleep_tom,"sleep");
    rose.addUser(tom.read_tom,"read");
    rose.eat();
    rose.sleep();
    rose.read();

</script>
  • 示例代碼4 : 訂閱者成為發(fā)布者
<script>
    //01 創(chuàng)建或者是設(shè)置一個發(fā)布者
    var publisher = {
        addUser:function(fn,type){
            var type = type || "eat";
            if (this.user[type] == undefined)
            {
                this.user[type] = [];
            }
            if (typeof fn != "function")
            {
                throw "不支持該操作!";
            }
            this.user[type].push(fn);
        },
        removeUser:function(fn,type){
            this.publish(type,fn);
        },
        publish:function(type,fn){
            var type = type || "eat";
            for (var i = 0; i < this.user[type].length; i++) {
                //判斷當(dāng)前是要取消訂閱還是要發(fā)布狀態(tài)
                if (typeof fn == "function")
                {
                    if(this.user[type][i] == fn)
                    {
                        console.log(fn + "取消了訂閱");
                        this.user[type].splice(i,1);
                    }
                }else
                {
                    this.user[type][i]();
                }

            }
        }
    }
    var rose = {
        eat:function(){
            this.publish("eat");
        },
        sleep:function(){
            this.publish("sleep");
        },
        read:function(){
            this.publish("read");
        },
        lol_rose:function(){
            console.log("你怎么又在打游戲?還是游戲比較重要一些?")
        }
    };
    function makePublisher(o){
        for(var i in publisher)
        {
            if (publisher.hasOwnProperty(i) && typeof publisher[i] == "function" ){
                o[i] = publisher[i];
            }
        }
        o.user = {
            eat:[],
            sleep:[]
        };
    }
    makePublisher(rose);

    var jack = {
        eat_jack:function(){
            console.log("我陪你去吃拉面吧  ---jack");
        },
        sleep_jack:function(){
            console.log("晚安 rose  ---jack");
        },
        statusLol:function(){
            this.publish("lol");
        }
    }
    var tom = {
        eat_tom:function(){
            console.log("我買給你吧  ---tom");
        },
        sleep_tom:function(){
            console.log("今晚的太陽很好看 ---tom");
        },
        read_tom:function(){
            console.log("你也在學(xué)習(xí)js嗎?");
        },
        lol_rose:function(){
            console.log("好兄弟,終于來啦");
        }
    }

    rose.addUser(jack.eat_jack,"eat");

    rose.addUser(tom.sleep_tom,"sleep");
    rose.addUser(tom.read_tom,"read");
    rose.eat();
    rose.sleep();
    rose.read();

    //設(shè)置jack成為發(fā)布者,狀態(tài)(lol)
    makePublisher(jack);
    jack.addUser(rose.lol_rose,"lol");
    jack.addUser(tom.lol_rose,"lol");
    jack.statusLol();

</script>

備忘模式(函數(shù)結(jié)構(gòu)緩存)

特定場合:

  • 計算的函數(shù)f()
  • 某些參數(shù)需要進(jìn)行大規(guī)模反復(fù)的計算,可以考慮吧計算的結(jié)果保存起來
    f(n) ..... =>1000m
    代碼中某些參數(shù)可能會反復(fù)計算
    f(10) ===>ssddd
    f(10) ===>ssddd

使用一個緩存對象cacheObj{key-value}

  • 思路:

1.提供一個全局的對象(緩存對象),key-value
2.當(dāng)我們傳遞參數(shù)需要進(jìn)行計算(邏輯)的時候,先檢查緩存對象中是否有對應(yīng)的結(jié)果
3.如果有緩存數(shù)據(jù),那么就直接使用(可以節(jié)省時間,提高效率)
4.如果沒有緩存數(shù)據(jù),那么這個時候再執(zhí)行計算操作,處理得到結(jié)果之后,把這個數(shù)據(jù)保存起來
5.函數(shù)的參數(shù)作為緩存對象的key,把函數(shù)計算的結(jié)果作為這個key對應(yīng)的值

  • 示例代碼 :
<script>
    var cache = {};
    function f1(str){
        //.....
        if (cache[str] != undefined)
        {
            console.log("已經(jīng)存在緩存數(shù)據(jù),直接返回");
            return cache[str];
        }
        //....如果緩存中有數(shù)據(jù),那么函數(shù)體后面的代碼就不再執(zhí)行(節(jié)省時間)

        //執(zhí)行耗時操作...
        var result = str + " hello world!";
        cache[str] = result;
        console.log("第一次調(diào)用函數(shù)傳入?yún)?shù),返回結(jié)果");
        return result;
    }

    console.log(f1("demo"));   //
    console.log(f1("demo"));   //
    console.log(f1("demo"));
</script>
<script>
    function f1(str){
        //.....
        if (f1.cache[str] != undefined)
        {
            console.log("已經(jīng)存在緩存數(shù)據(jù),直接返回");
            return f1.cache[str];
        }
        //....如果緩存中有數(shù)據(jù),那么函數(shù)體后面的代碼就不再執(zhí)行(節(jié)省時間)

        //執(zhí)行耗時操作...
        var result = str + " hello world!";
        f1.cache[str] = result;
        console.log("第一次調(diào)用函數(shù)傳入?yún)?shù),返回結(jié)果");
        return result;
    }

    f1.cache = {};
    console.log(f1("test"));  //
    console.log(f1("test"));   //
    console.log(f1("test"));
</script>

命名空間模式:

寫法:就是把所有的東西都寫在一個對象里面.

命名:命名空間的名稱一般是項目的名稱或者是簡寫,要求所有的字符都大寫

  • 示例代碼 :
<script>
    //01 普通的變量
    var a = "a";
    var b = "b";

    //02 對象
    var obj = {
        name:"xxx"
    }

    function func (){
        console.log("func");
    }

    function Person(){
        this.name = "默認(rèn)的名稱";
    }
    function func (){
        console.log("func");
    }
</script>
<script>
    var MOMO = {};
    //01 普通的變量
    MOMO.a = "a";
    MOMO.b = "b";

    //02 對象
    MOMO.obj = {
        name:"zahngsan"
    }

    MOMO.func = function(){
        console.log("func");
    }

    MOMO.Person = function(){
        this.name = "默認(rèn)的名稱";
    }

    console.log(new  MOMO.Person());
</script>
<script>
//    var MOMO ={};
//    MOMO.obj = {
//        name:"張三"
//    };
//
//    MOMO.obj = "demodede";

    //在使用或者是對屬性進(jìn)行賦值之前,會先做一個檢查(檢查改屬性或者是方法是否存在)
    //var MOMO = {};  不推薦

    //02 更安全的處理方式:麻煩
//    if (MOMO == undefined)
//    {
//        var MOMO = {};
//    }

    var MOMO = MOMO || {};      //邏輯或 如果MOMO為真那么返回MOMO,否則就返回{}
    //if (MOMO.name == undefined)
    if ( typeof MOMO.name == 'undefined')
{
    MOMO.name = "測試的名稱";
}

    if ( typeof MOMO.age == 'undefined')
    {
        MOMO.age = 20;
    }

    //100屬性

</script>

通用的命名空間函數(shù)

在命名空間上面提供一個方法(nameSpace)

  • 得到調(diào)用函數(shù)傳入的字符串
  • 把字符串轉(zhuǎn)換為字符串?dāng)?shù)組
  • 把MOMO最外層去掉(刪除)
  • 遍歷
  • 示例代碼 :
<script>
    var MOMO = MOMO || {};
    MOMO.namespace = function(stringParam){
        var str = stringParam;
        var parts = str.split(".");   //根據(jù)字符串切割字符串變成一個數(shù)組
        var parent = MOMO;

        console.log(parts);

        if(parts[0] == "MOMO")
        {
            parts = parts.slice(1)    //作用:刪除第一個元素返回一個新的數(shù)組
        }

        for (var i = 0; i < parts.length; i++) {
            //MOMO.name
            //name.des
            //des.abc
            if (parent[parts[i]] == undefined)
            {
                parent[parts[i]] = {};
            }
            //更新父節(jié)點(diǎn)
            parent = parent[parts[i]];
        }
    }

    MOMO.namespace("MOMO.name.des.abc");
    console.log(MOMO);

    MOMO.namespace("MOMO.a.b.c.d.e.f.d.g.h.j.k.s.d.g.h.j.a.s.d.f.we.r");
    console.log(MOMO);
    MOMO.namespace("abc.des.abc");
    console.log(MOMO);
</script>

截至今日,面向?qū)ο蠛蚃avaScript進(jìn)階內(nèi)容已經(jīng)全部更新完畢! 內(nèi)容是比較詳細(xì)的,只要跟著每一篇的博文仔細(xì)學(xué)習(xí),比你看網(wǎng)上的垃圾視頻強(qiáng)多了 ! 理論和實(shí)踐相結(jié)合 更多的是得動手去敲,以后還請大家多多關(guān)注更新,日后定會上一些新穎的東西和大家見面 !


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椰苟,一起剝皮案震驚了整個濱河市宾抓,隨后出現(xiàn)的幾起案子子漩,更是在濱河造成了極大的恐慌,老刑警劉巖石洗,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幢泼,死亡現(xiàn)場離奇詭異,居然都是意外死亡讲衫,警方通過查閱死者的電腦和手機(jī)缕棵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涉兽,“玉大人招驴,你說我怎么就攤上這事〖衔罚” “怎么了别厘?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拥诡。 經(jīng)常有香客問我触趴,道長,這世上最難降的妖魔是什么渴肉? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任冗懦,我火速辦了婚禮,結(jié)果婚禮上仇祭,老公的妹妹穿的比我還像新娘披蕉。我一直安慰自己,他們只是感情好乌奇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布嚣艇。 她就那樣靜靜地躺著,像睡著了一般华弓。 火紅的嫁衣襯著肌膚如雪食零。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天寂屏,我揣著相機(jī)與錄音贰谣,去河邊找鬼娜搂。 笑死,一個胖子當(dāng)著我的面吹牛吱抚,可吹牛的內(nèi)容都是我干的百宇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼秘豹,長吁一口氣:“原來是場噩夢啊……” “哼携御!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起既绕,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤啄刹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后凄贩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體誓军,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年疲扎,在試婚紗的時候發(fā)現(xiàn)自己被綠了昵时。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡椒丧,死狀恐怖壹甥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情壶熏,我是刑警寧澤句柠,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站久橙,受9級特大地震影響俄占,放射性物質(zhì)發(fā)生泄漏管怠。R本人自食惡果不足惜淆衷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渤弛。 院中可真熱鬧祝拯,春花似錦、人聲如沸她肯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晴氨。三九已至康嘉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間籽前,已是汗流浹背亭珍。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工敷钾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肄梨。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓阻荒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親众羡。 傳聞我的和親對象是個殘疾皇子侨赡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

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

  • 老劉最近把朋友圈關(guān)了羊壹。 我打電話給他約他出來吃飯,問他:“你這么一個不安分的人甜害,怎么突然一下子把朋友圈關(guān)了舶掖?” 老...
    大貓卡門閱讀 450評論 0 0
  • 參加于斯的文化培訓(xùn)課聽了韓冰老師的599,方百里老師的指法練習(xí)教材尔店,還有宋涵老師的小湯等教材眨攘,受益很多,每位老師都...
    胡美美閱讀 805評論 0 3
  • 不知從何時開始嚣州,“宮寒”一詞闖入女人們的生活鲫售。 不管是小到月經(jīng)不調(diào)、痛經(jīng)该肴,還是大到不孕不育情竹,除了癌癥,幾乎所有婦科...
    沐晨雨rara閱讀 1,227評論 0 0
  • 今天上班第一天匀哄,我就長了個記性秦效,媽呀我的小電驢居然追尾人家,傷心π_π涎嚼,我還重重摔了一跤阱州,摔在地上的時候我還起不來...
    言如心閱讀 202評論 0 0