摘要:假設(shè)有一個(gè)生產(chǎn)交通工具的工廠類,它包含生成多種交通工具實(shí)例的方法。在使用這個(gè)類生產(chǎn)對(duì)象的時(shí)候,傳入?yún)?shù),在參數(shù)中的屬性規(guī)定我們需要的類型,構(gòu)造函數(shù)就能夠返回我們需要的對(duì)象類型了。
一般來(lái)說(shuō),創(chuàng)建對(duì)象的時(shí)候我們都習(xí)慣使用new關(guān)鍵字來(lái)調(diào)用constructor構(gòu)造函數(shù),但使用這種方式會(huì)有一些缺點(diǎn),首先構(gòu)造器函數(shù)的創(chuàng)建本身就是為了模仿其他一些面向?qū)ο笳Z(yǔ)言的特性,有些人覺(jué)得這是non-sense;另一方面,在一個(gè)類中用new關(guān)鍵字調(diào)用其他類的構(gòu)造函數(shù),會(huì)造成兩個(gè)類之間的耦合,設(shè)計(jì)模式應(yīng)該要盡量避免這些影響代碼可重用性的問(wèn)題。
簡(jiǎn)單工廠模式一個(gè)工廠可以生產(chǎn)同一類的多種物品,具體生產(chǎn)哪種就看客戶下什么訂單了。工廠模式也是一樣,我們創(chuàng)建一個(gè)工廠類,它可以創(chuàng)建多種實(shí)例,由開(kāi)發(fā)者指定。
假設(shè)有一個(gè)生產(chǎn)交通工具的工廠類Vehicle,它包含生成多種交通工具實(shí)例的方法。
function Vehicle() {} Vehicle.prototype = { createVihicle: function(options) { var vehicle; switch(options.type) { case "car": vehicle = new Car(); break; case "truck": vehicle = new Truck(); break; default: vehicle = new Bike(); } return vehicle; } };
在使用這個(gè)類生產(chǎn)對(duì)象的時(shí)候,傳入option參數(shù),在參數(shù)中的type屬性規(guī)定我們需要的類型,構(gòu)造函數(shù)就能夠返回我們需要的對(duì)象類型了。使用這種方法,如果我們要添加新的交通工具類型也是很方便的,在工廠的switch中直接添加一個(gè)case就可以了。
switch(options.type) { case "car": vehicle = new Car(); break; case "truck": vehicle = new Truck(); break; case "plane": vehicle = new Plane(); break; default: vehicle = new Bike(); }
通過(guò)這種方式,將成員對(duì)象的創(chuàng)建工作轉(zhuǎn)交給外部對(duì)象,可以像上述代碼一樣轉(zhuǎn)交給獨(dú)立的命名空間,像Car,Truck,Plane等,如果外部對(duì)象屬于同一類的話,將它們組織為一個(gè)大類中的子類比較合理。
工廠模式以上介紹的是簡(jiǎn)單工廠模式,簡(jiǎn)單工廠模式會(huì)把創(chuàng)建工作交給外部的類來(lái)做,這實(shí)際上會(huì)增加類的數(shù)量,并不利于代碼的組織。真正的工廠模式會(huì)把創(chuàng)建工作交給子類來(lái)完成,父類只對(duì)創(chuàng)建過(guò)程中的一般性問(wèn)題進(jìn)行處理,這些處理會(huì)影響到每個(gè)子類,而子類之間相互獨(dú)立,可以對(duì)創(chuàng)建過(guò)程進(jìn)行一些定制化操作。
還是以生產(chǎn)交通工具為例,將交通工具父類改寫(xiě)為一個(gè)抽象類,它不負(fù)責(zé)直接生產(chǎn)交通工具,而是通過(guò)它派生出一些子類,這些子類代表不同的國(guó)家,不同的國(guó)家可以生產(chǎn)自己的交通工具。
將父類抽象化:
function Vehicle() {} Vehicle.prototype = { createVihicle: function(options) { // 這里不直接生產(chǎn),如果直接調(diào)用會(huì)拋出錯(cuò)誤 throw new Error("Unsupported operation on an abstract class.") } };
不同的國(guó)家作為子類,子類首先對(duì)父類進(jìn)行繼承,然后實(shí)現(xiàn)自己的createVehicle方法。
function China() {} // 繼承方法 extend(China, Vehicle); // 實(shí)現(xiàn)自己的createVehicle方法 China.prototype.createVehicle = function(options) { var vehicle; switch(options.type) { case "car": vehicle = new Car(); break; case "truck": vehicle = new Truck(); break; default: vehicle = new Bike(); } return vehicle; }
以后要生產(chǎn)交通工具的時(shí)候就調(diào)用China子類的createVehicle方法就可以了。
var chinaVehicle = new China(); var myCar = chinaVehicle.createVehicle({ type: "Car" });
一般性的代碼集中在父類中,個(gè)性化的代碼在子類中多帶帶定制。
工廠模式適用場(chǎng)合子類的共同點(diǎn)是它們都實(shí)現(xiàn)了同一批接口,盡管內(nèi)部細(xì)節(jié)并不盡相同。生產(chǎn)對(duì)象的方法有一個(gè)選擇性的過(guò)程,這種選擇可以是開(kāi)發(fā)者自定的,比如需要生產(chǎn)何種交通工具,也可以是自動(dòng)選擇的,比如根據(jù)瀏覽器環(huán)境生產(chǎn)合適的XHR對(duì)象。對(duì)于相似性很高,實(shí)現(xiàn)了同一類接口的對(duì)象,工廠模式是比較合適的。
另外的一大好處就是子類的一些設(shè)置代碼可以全部放在父類的構(gòu)造器函數(shù)中,不需要在每個(gè)子類的構(gòu)造函數(shù)中重復(fù)運(yùn)行同樣的代碼,只需要在父類的代碼中實(shí)現(xiàn)一次就好。子類只需要專注于實(shí)現(xiàn)自己的方法,不用考慮別的問(wèn)題。
最后一點(diǎn)則是如果一個(gè)類中包含了很多更小的子類作為自己的組成部分,那么替換這些子類的工作會(huì)很簡(jiǎn)單,因?yàn)楣S模式降低了模塊之間的耦合度,一個(gè)模塊并不會(huì)依賴于其某一組成部分。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/87528.html
摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方法和的作用都是在某個(gè)特殊對(duì)象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無(wú)區(qū)別適用情境可以在特殊的情況下用來(lái)為對(duì)象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:使用構(gòu)造器有個(gè)嚴(yán)重的危害,如果在調(diào)用構(gòu)造器函數(shù)的時(shí)候忘記使用前綴,不僅不會(huì)綁定到新對(duì)象,還會(huì)污染全局變量原型模式原型模式中,我們采用對(duì)象來(lái)繼承。 構(gòu)造器調(diào)用模式 當(dāng)一個(gè)函數(shù)對(duì)象被創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器會(huì)運(yùn)行類似這樣的代碼: this.prototype = {constructor: this} new一個(gè)函數(shù)事會(huì)發(fā)生: Function.method(new, functio...
命名空間 var MYNAMESPACE = MYNAMESPACE || {}; //構(gòu)造函數(shù) MYNAMESPACE.Child = function () {} // 變量 MYNAMESPACE.mystr= 6-ara forerer MYNAMESPACE.Person = function(name) { this.name = name; }; //原型 MYNAMES...
摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...
摘要:具體檢查方式則是檢查對(duì)象是否實(shí)現(xiàn)了接口所聲明的所有方法。組合模式將對(duì)象群體與組成對(duì)象同等對(duì)待。裝飾者模式透明地為另一對(duì)象提供包裝,實(shí)現(xiàn)相同的接口。 Javascript 中模仿接口的三種方法 1. 注釋描述 /* interface Composite { function add(child); function remove(child); function ge...
閱讀 3221·2021-11-23 09:51
閱讀 3563·2021-11-09 09:46
閱讀 3670·2021-11-09 09:45
閱讀 2943·2019-08-29 17:31
閱讀 1865·2019-08-26 13:39
閱讀 2724·2019-08-26 12:12
閱讀 3622·2019-08-26 12:08
閱讀 2242·2019-08-26 11:31