亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

鏈?zhǔn)秸{(diào)用&工廠

Lemon_95 / 922人閱讀

摘要:鏈?zhǔn)秸{(diào)用精髓在于重用一個(gè)初始操作可以把方法的鏈?zhǔn)秸{(diào)用技術(shù)寫(xiě)到自己所寫(xiě)的整個(gè)庫(kù)中把自己喜歡的方法串起來(lái)調(diào)用兩個(gè)部分一個(gè)創(chuàng)建代表元素的對(duì)象的工廠還有一批對(duì)這個(gè)元素執(zhí)行某些操作的方法每一個(gè)這種方法都可以在方法名前附加一個(gè)圓點(diǎn)后加入調(diào)用鏈中方法的鏈

鏈?zhǔn)秸{(diào)用 精髓在于重用一個(gè)初始操作.
可以把方法的鏈?zhǔn)秸{(diào)用技術(shù)寫(xiě)到自己所寫(xiě)的整個(gè) js 庫(kù)中,把自己喜歡的方法串起來(lái)調(diào)用.兩個(gè)部分:一個(gè)創(chuàng)建代表 HTML 元素的對(duì)象的工廠,還有一批對(duì)這個(gè) HTML 元素執(zhí)行某些操作的方法.每一個(gè)這種方法都可以在方法名前附加一個(gè)圓點(diǎn)后加入調(diào)用鏈中.方法的鏈?zhǔn)秸{(diào)用可以被視為選擇網(wǎng)頁(yè)上的一個(gè)元素并對(duì)其進(jìn)行多個(gè)操作的過(guò)程.
addEvent($(".example"), "click", function () {
    // Without chaining:
    $(this).hide();
    setStyle(this, "color", "green");
    $(this).show();

    // With chaining;
    $(this).hide().setStyle("color", "green").show();
});
調(diào)用鏈結(jié)構(gòu)

$函數(shù)通常會(huì)返回一個(gè)HTML 元素(的集合):

function $() {
    var eles = [];
    for (var i = 0, len = arguments.length; i < len; ++i) {
        var ele = arguments[i];
        if (typeof ele === "string") {
            ele = document.getElementById(ele);
        }
        if (arguments.length === 1) {
            return ele;
        }
        eles.push(ele);
    }
    return eles;
}

如果把這個(gè)函數(shù)改造成一個(gè)構(gòu)造器,把那些元素作為數(shù)組保存在一個(gè)實(shí)例屬性中,并讓所有定義在構(gòu)造器函數(shù)的 prototype 屬性所指對(duì)象中的方法都返回用來(lái)調(diào)用方法的那個(gè)實(shí)例的引用,那么它就具有鏈?zhǔn)秸{(diào)用的能力.
做一下改進(jìn):首先把$函數(shù)改成一個(gè)工廠方法,負(fù)責(zé)創(chuàng)建支持鏈?zhǔn)秸{(diào)用的對(duì)象,這個(gè)函數(shù)應(yīng)該能接受元素?cái)?shù)組形式的參數(shù),所以我們能夠使用和原來(lái)一樣的公有接口:

(function () {
    // Use a private class.
    function _$(els) {
        this.eles = [];
        for (var i = 0, len = els.length; i < len; ++i) {
            var ele = els[i];
            if (typeod ele === "string") {
                ele = document.getElementById(ele);
            }
            this.eles.push(ele);
        }
    }

    // The public interface remains the same.
    window.$ = function () {
        return new _$(arguments);
    };
})();

由于所有對(duì)象都會(huì)繼承其原型對(duì)象的屬性和方法,所以我們可以讓定義在原型對(duì)象中的那幾個(gè)方法都返回用以調(diào)用方法的實(shí)例對(duì)象的引用,這樣就可以對(duì)哪些方法進(jìn)行鏈?zhǔn)秸{(diào)用.現(xiàn)在在_$這個(gè)私有構(gòu)造函數(shù)的 prototype 對(duì)象中添加方法:

(function () {
    function _$(eles) {
        // ...
    }
    _$.prototype = {
        each: function (fn) {
            for (var i = 0, len = this.eles.length; i < len; ++i) {
                fn.call(this, this.eles[i]);
            }
            return this;
        },
        hide: function (0 {
            var that = this;
            this.setStyle("display", "none");
        });
        setStyle: function (prop, val) {
            this.each(function (ele) {
                ele.style[prop] = val;
            });
            return this;
        },
        show: function (0 {
            var that = this;
            this.setStyle("display", "block");
        });
        return this;
        addEvent: function(type, fn) {
            var add = function (ele) {
                if (window.addEventListener) {
                    ele.addEventList(type, fn, false);
                }
                else if (window.attachEvent) {
                    ele.attachEvnet("on" + type, fn);
                }
            };
            this.each(function (el) {
                add(el);
            });
            return this;
        }
    };
    window.$ = function () {
        return new _$(arguments);
    };
})();

每個(gè)方法的最后一行return this;會(huì)講調(diào)用方法對(duì)象傳給調(diào)用鏈上的下一個(gè)方法.
jQuery 便是這樣,window 對(duì)象或者某個(gè) HTML 元素是調(diào)用鏈的錨點(diǎn),多有操作都掛系在上面.

使用回調(diào)從支持鏈?zhǔn)秸{(diào)用的方法獲取數(shù)據(jù)

鏈?zhǔn)秸{(diào)用很適合于賦值器方法,但是對(duì)于取值器方法,并不希望方法返回 this.不過(guò)使用回調(diào)技術(shù)可以返回你想要的數(shù)據(jù)而不是 this.

// Accessor without function callbacks: returning requested data in accessors.
window.API = window.API || function () {

    var name = "Hello world";
    // Privilleged mutator
    this.setName = function(newName) {
        name = newName;
        return this;
    };
    // Privileged accessor method.
    this.getName = function () {
        return name;
    };

};

// Implementation code
var o = new API;
console.log(o.getName()); // Displays "Hello world".
console.log(o.setName("nanci").getName()); // Display "nanci"

// Accessor with function callbacks.
window.API2 = window.API2 || function () {

    var name = "Hello world";
    // Privilleged mutator
    this.setName = function(newName) {
        name = newName;
        return this;
    };
    // Privileged accessor method.
    this.getName = function (callback) {
        callback.call(this, name);
        return this;
    };

}

// Implementation code
var o2 = new API2;
o2.getName(console.log).setName("nanci").getName(console.log); // Displays "Hello world" and then display "nanci"
小結(jié)

使用鏈?zhǔn)秸{(diào)用可以避免多次重復(fù)使用一個(gè)對(duì)象變量,減少代碼量.
如果想讓類的接口保持一致,讓取值器像賦值器那樣也支持鏈?zhǔn)秸{(diào)用,那么可以使用回調(diào).

----------another part----------

工廠
一個(gè)類或者對(duì)象中可能包含別的對(duì)象.在創(chuàng)建這種成員對(duì)象時(shí),可以使用 new 關(guān)鍵字或者類構(gòu)造函數(shù).但是會(huì)導(dǎo)致兩個(gè)類產(chǎn)生依賴.工廠模式就是用來(lái)消除這種依賴.他使用一個(gè)方法來(lái)決定究竟要實(shí)例化哪個(gè)具體的類.簡(jiǎn)單的工廠使用一個(gè)類(通常是單體)來(lái)生成實(shí)例,復(fù)雜的工廠模式使用子類來(lái)決定一個(gè)成員變量應(yīng)該是哪個(gè)具體的類的實(shí)例.
簡(jiǎn)單工廠

如果你想開(kāi)幾個(gè)自行車(chē)商店,每個(gè)店都有幾種型號(hào)的自行車(chē)出售,用一個(gè)類表示:

// BicycleShop class.

var BicycleShop = function () {};
BicycleShop.prototype = {
    sellBicycle: function(model) {
        var bicycle;

        switch(model) {
            case "The Speedter":
                bicycle = new Speedter();
                break;
            case "The Lowrider":
                bicycle = new Lowrider();
                break;
            case "The Comfort Cruiser":
            default:
                bicycle = new ComfortCruiser();
        }

        Interface.ensureImplements(bicycle, Bicycle);
        bicycle.assemble();
        bicycle.wash();

        return bicycle;
    }
};

sellBicycle 方法根據(jù)所要求的自行車(chē)型號(hào)用 switch 語(yǔ)句創(chuàng)建一個(gè)自行車(chē)的實(shí)例.各種型號(hào)的自行車(chē)實(shí)例可以互換使用,因?yàn)樗麄兌紝?shí)現(xiàn)了 Bicycle 接口(接口在工廠中很重要,如果不對(duì)對(duì)象進(jìn)行某種類型檢查以其確保其實(shí)現(xiàn)了必須的方法,那么工廠模式并不能帶來(lái)什么好處).

// The Bicycle interface.

var Bicycle = new Interface("Bicycle", ["assemble", "wash", "ride", "repair"]);

// Speedster class.
var Speedster = function () { // implement Bicycle
    ...
};
Speedster.prototype = {
    assemble: function () {
        ...
    },
    wash: function () {
        ...
    },
    ride: function () {
        ...
    },
    repair: function () {
        ...
    }
};

要出售某種型號(hào)自行車(chē),只需要調(diào)用 sellBicycle 方法即可:

var californiaCruisers = new BicycleShop();
var yourNewBike = californiaCruisers.sellBicycle("The Speedster");

如果你想在供貨目錄中加入一款新車(chē)型,更好的解決辦法是把 sellBicycle 方法中"創(chuàng)建新實(shí)例"這部分工作轉(zhuǎn)交給一個(gè)簡(jiǎn)單工廠對(duì)象.

// BicycleFactory namespace.

var BicycleFactory = {
    createBicycle: function (model) {
        var bicycle;

        switch(model) {
            case "The Speedter":
                bicycle = new Speedter();
                break;
            case "The Lowrider":
                bicycle = new Lowrider();
                break;
            case "The Comfort Cruiser":
            default:
                bicycle = new ComfortCruiser();
        }

        Interface.ensureImplements(bicycle, Bicycle);
        return bicycle;
    }
};

BicycleFactory 是一個(gè)單體,用來(lái)把 createBicycle 方法封裝在一個(gè)命名空間中,這個(gè)方法返回一個(gè)實(shí)現(xiàn)了 Bicycle接口的對(duì)象,然后可以對(duì)其進(jìn)行組裝和清洗:

// BicycleShop class, improved.

var BicycleShop = function () {};
BicycleShop.prototype = {
    sellBicycle: function (model) {
        var bicycle = BicycleFactory.createBicycle(model);

        bicycle.assemble();
        bicycle.wash();

        return bicycle;
    }
};

這個(gè) BicycleFactory 對(duì)象可以供各種類用來(lái)創(chuàng)建新的自行車(chē)實(shí)例.有關(guān)可供車(chē)型的所有信息都集中在一個(gè)地方管理,所以添加更多車(chē)型很容易:

// BicycleFactory namespace, with more models.

var Bicycle: function (model) {

    var bicycle;

    switch (model) {
        case "The Speedster":
            bicycle = new Speedster();
            break;
        case "The Lowrider":
            bicycle = new Lowrider();
            break;
        case "The Flatlander":
            bicycle = new Flatlander();
            break;
        case "The ComfortCruiser":
            bicycle = new ComfortCruiser();
    }

    Interface.ensureImplements(bicycle, Bicycle);
    return bicycle;
}

這是一個(gè)簡(jiǎn)單工廠的例子,他把成員對(duì)象的創(chuàng)建工作交給一個(gè)外部對(duì)象,這個(gè)外部對(duì)象可以是一個(gè)簡(jiǎn)單的命名空間,也可以是一個(gè)類的實(shí)例.

示例: XHR 工廠

用 Ajax 技術(shù)發(fā)起異步請(qǐng)求是現(xiàn)在 Web 開(kāi)發(fā)的一個(gè)常見(jiàn)任務(wù).用于發(fā)起請(qǐng)求的對(duì)象是某種類的實(shí)例,具體是哪種類取決于用戶的瀏覽器.如果代碼中需要多次執(zhí)行 ajax 請(qǐng)求,那么可以把創(chuàng)建這種對(duì)象的代碼提取到一個(gè)類中,并創(chuàng)建一個(gè)包裝器來(lái)包裝在實(shí)際發(fā)起請(qǐng)求時(shí)所要經(jīng)歷的一系列步驟,簡(jiǎn)單工廠非常適合該場(chǎng)合,根據(jù)瀏覽器特性生成一個(gè) XMLHttpRequest 或者 ActiveXObject 實(shí)例.

// AjaxHandler interface.
var AjaxHandler = new Interface("AjaxHandler", ["request", "createXhrObject"]);

// SimpleHandler class.

var SimleHandler = function () {}; // implements AjaxHandler
SimpleHandler.prototype = {
    request: function (method, url, callback, postVars) {
        var xhr = this.createXhrObject();
        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            (xhr.status === 200) ? callback.success(xhr.responseText) : callback.failure(xhr.status);
        };
        xhr.open(method, url, true);
        if (method !== "POST") {
            postVars = null;
        }
        xhr.send(postVars);
    },
    createXhrObject: function () { // Factory method.
        var methods = [
            function () {
                return newXMLHttpRequest();
            },
            function () {
                return new ActiveXObject("Msxml2.XMLHTTP");
            },
            function () {
                return new ActiveXObject("Microsoft.XMLHTTP");
            }
        ];

        for (var i =0, len = methods.length; i < len; i++) {
            try {
                methods[i]();
            }
            catch(e) {
                continue;
            }

            //If we reach this point, method[i] worked.
            this.createXhrObject = methods[i]; //Memoize the method.
            return methods[i];
        }

        // If we reach this point, none of the methods worked.
        throw new Error("SimpleHandler: Could not create an XHR object.");
    }
}

主要好處在于消除對(duì)象間的耦合,通過(guò)使用工廠方法而不是 new 關(guān)鍵字及具體類,你可以把所有實(shí)例化代碼集中在一個(gè)位置.可以大大簡(jiǎn)化更換所用的類或者在運(yùn)行期間動(dòng)態(tài)選擇所有的類的工作.在派生子類時(shí)也更靈活.可以先創(chuàng)建一個(gè)抽象的超類,然后在子類中創(chuàng)建工廠方法,從而把成員對(duì)象的實(shí)例化推遲到更專門(mén)化的子類中進(jìn)行.
所有這些好處都和面向?qū)ο笤O(shè)計(jì)的兩條原則相關(guān): 弱化對(duì)象間的耦合:防止代碼的重復(fù).在一個(gè)方法中進(jìn)行類的實(shí)例化,可以消除重復(fù)性的代碼.這是在用一個(gè)對(duì)接口的調(diào)用取代一個(gè)具體的實(shí)現(xiàn).這些都有助于模塊化代碼.

不能把工廠方法當(dāng)萬(wàn)金油,而把普通函數(shù)扔在以便.如果根本不可能另外換用一個(gè)類或者不需要在運(yùn)行期間在一系列類的選擇,那么就不應(yīng)該使用工廠方法.大多數(shù)最好使用 new 關(guān)鍵字和構(gòu)造函數(shù)公開(kāi)進(jìn)行實(shí)例化,這樣代碼會(huì)更簡(jiǎn)單易讀..一眼就看到調(diào)用的構(gòu)造函數(shù),不必去查看某個(gè)工廠方法去知道實(shí)例化的是什么類.

小結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/87903.html

相關(guān)文章

  • 匯總有關(guān)JS對(duì)象的創(chuàng)建與繼承

      之前也有和大家講過(guò)有關(guān)JS的對(duì)象創(chuàng)建和對(duì)象繼承,本篇文章主要為大家做個(gè)匯總和梳理?! S中其實(shí)就是原型鏈繼承和構(gòu)造函數(shù)繼承的毛病,還有就是工廠、構(gòu)造、原型設(shè)計(jì)模式與JS繼承。 JS高級(jí)程序設(shè)計(jì)4:class繼承的重點(diǎn),不只是簡(jiǎn)簡(jiǎn)單單的語(yǔ)法而已。  對(duì)象創(chuàng)建  不難發(fā)現(xiàn),每一篇都離不開(kāi)工廠、構(gòu)造、原型這3種設(shè)計(jì)模式中的至少其一!  那JS為什么非要用到這種3種設(shè)計(jì)模式了呢??  我們先從對(duì)...

    3403771864 評(píng)論0 收藏0
  • Pytest架構(gòu)之fixture詳細(xì)說(shuō)明(三)

      原文中詳細(xì)的講解了Pytest架構(gòu)之fixture,原文中根據(jù)實(shí)例編碼推薦的十分詳盡。對(duì)大家學(xué)習(xí)培訓(xùn)和工作具有很強(qiáng)的參閱參考意義,需用的小伙伴可以參考一下  原文中有關(guān)fixture的具體內(nèi)容如下所示:  1、參數(shù)化設(shè)計(jì)fixture  2、fixture工廠  3、request這一fixture  1、參數(shù)化設(shè)計(jì)fixture  fixture有個(gè)params主要參數(shù),容許大家傳送數(shù)據(jù)。 ...

    89542767 評(píng)論0 收藏0
  • setInterval與setTimeout

    摘要:第二個(gè)調(diào)用當(dāng)前執(zhí)行的函數(shù),并為其設(shè)置另外一個(gè)定時(shí)器。使得在前一個(gè)定時(shí)器代碼執(zhí)行完之前,不會(huì)向隊(duì)列插入新的定時(shí)器代碼,確保不會(huì)有任何缺失的間隔。 在自己用canvas畫(huà)一個(gè)時(shí)鐘時(shí),畫(huà)秒鐘用的是利用圖片將重復(fù)的線條遮住,但是會(huì)出現(xiàn)有兩個(gè)秒鐘線條同時(shí)存在,才想起setInterval有那么個(gè)坑,查了點(diǎn)資料,記錄下,若有不對(duì)的或者未寫(xiě)到的點(diǎn),還請(qǐng)大家指出,謝謝^_^ 在此之前先科普下這個(gè)學(xué)習(xí)點(diǎn)...

    BenCHou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<