摘要:使用完全模式省略每個(gè)品牌的獨(dú)有的屬性方法這是一輛單車抽象工廠模式抽象工廠模式通過(guò)對(duì)類的工廠抽象使其業(yè)務(wù)用于對(duì)產(chǎn)品類簇的創(chuàng)建,而不負(fù)責(zé)創(chuàng)建某一類產(chǎn)品的實(shí)例。抽象類是一種聲明但不能使用的類,當(dāng)你使用時(shí)就會(huì)報(bào)錯(cuò)。
原文博客地址:https://finget.github.io/2018/10/12/factory/工廠模式 簡(jiǎn)介
工廠模式定義一個(gè)用于創(chuàng)建對(duì)象的接口,這個(gè)接口由子類決定實(shí)例化哪一個(gè)類。該模式使一個(gè)類的實(shí)例化延遲到了子類。而子類可以重寫接口方法以便創(chuàng)建的時(shí)候指定自己的對(duì)象類型(抽象工廠)。
將 new 操作多帶帶封裝,遇到new時(shí),就要考慮是否該用工廠模式
模式作用:
對(duì)象的構(gòu)建十分復(fù)雜
需要依賴具體的環(huán)境創(chuàng)建不同實(shí)例
處理大量具有相同屬性的小對(duì)象
注意事項(xiàng):
不能濫用工廠,有的時(shí)候僅僅是給代碼增加復(fù)雜度
UML
// product class jQuery { constructor(selector) { let slice = Array.prototype.slice let dom = slice.call(document.querySelectorAll(selector)) let len = dom ? dom.length : 0 for (let i = 0; i < len; i++) { this[i] = dom[i] } this.length = len this.selector = selector || "" } append(node) {} addClass(name) {} html(data) {} // 此處省略若干 API } // 工廠 window.$ = function (selector) { return new jQuery(selector) }簡(jiǎn)單工廠 與 抽象工廠 簡(jiǎn)單工廠模式
簡(jiǎn)單工廠模式:又叫靜態(tài)工廠方法,由一個(gè)工廠對(duì)象決定創(chuàng)建某一種產(chǎn)品對(duì)象類的示例。主要用來(lái)創(chuàng)建同一類對(duì)象。
去KFC點(diǎn)一個(gè)漢堡,服務(wù)員給你的是個(gè)漢堡,而不是牛肉、面粉、佐料...
// KFC的類 class KFC { // 做漢堡 makeHbg () { // ...繁瑣的工序 console.log("漢堡一個(gè)") } // 炸雞腿 makeChk () { // ...繁瑣的工序 console.log("雞腿一個(gè)") } } // 某一家KFC的店鋪 let kfcFactory = function (food) { let kfc = new KFC() switch (food) { case hamburger: return kfc.makeHbg() break; case chicken: return kfc.makeChk() break; } } // 對(duì)于顧客來(lái)說(shuō),他只需要‘傳入’他需要的東西就好了,不用關(guān)心漢堡是怎么做出來(lái)的 kfcFactory(hamburger); // "漢堡一個(gè)"工廠方法
工廠方法:通過(guò)對(duì)產(chǎn)品類的抽象使其創(chuàng)建業(yè)務(wù)主要負(fù)責(zé)用于創(chuàng)建多類產(chǎn)品的實(shí)例。
現(xiàn)在有個(gè)工廠來(lái)生成所有的共享單車,模擬一下工廠模式。
// 別較真 栗子不好吃 理解這種方式就行 let Ofo = function() { this.name = "ofo" // ... 省略每個(gè)品牌的獨(dú)有的屬性方法 (function() { let div = document.createElement("div") div.innerHTML = "這是一輛ofo單車" document.getElementById("box").appendChild(div) })() } let Mobike = function() { this.name = "Mobike" // ... 省略每個(gè)品牌的獨(dú)有的屬性方法 (function() { let div = document.createElement("div") div.innerHTML = "這是一輛Mobike單車" document.getElementById("box").appendChild(div) })() } let Hello = function() { this.name = "hello" // ... 省略每個(gè)品牌的獨(dú)有的屬性方法 (function() { let div = document.createElement("div") div.innerHTML = "這是一輛hello單車" document.getElementById("box").appendChild(div) })() } let Blue = function() { this.name = "blue" // ... 省略每個(gè)品牌的獨(dú)有的屬性方法 (function() { let div = document.createElement("div") div.innerHTML = "這是一輛blue單車" document.getElementById("box").appendChild(div) })() } let Bikefactory = function (type) { switch (type) { case "Ofo": return new Ofo() break; case "Mobike": return new Mobike() break; case "Hello": return new Hello() break; case "Blue": return new Blue() break; } }安全模式類
安全模式類是為了解決錯(cuò)誤使用類而造成的錯(cuò)誤。
var Demo = function() {} Demo.prototype={ show: function() { console.log("Hello Demo") } } // 正確使用 var d = new Demo() d.show(); // 錯(cuò)誤使用 var d = Demo() d.show(); // Uncaught TypeError:Cannot read property "show" of undefined
為了避免這類錯(cuò)誤的發(fā)生,在構(gòu)造函數(shù)開始時(shí)先判斷當(dāng)前對(duì)象this指代的是不是類(Demo)。
var Demo = function () { if (!(this instanceof Demo)) { return new Demo() } } var d =Demo(); d.show(); // "Hello Demo"
上面這樣寫,我們發(fā)現(xiàn)當(dāng)共享單車的種類越來(lái)越多,需要添加新的共享單車時(shí),就需要修改兩處的代碼,所以可以對(duì)它進(jìn)行修改,按工廠模式方法來(lái)做。
let Bikefactory = function (name) { // 使用完全模式 if (this instanceof Bikefactory) { let s = new this[type](name) return s; } else { return new Bikefactory(name) } } Bikefactory.prototype = { Ofo: function() { this.name = "ofo" // ... 省略每個(gè)品牌的獨(dú)有的屬性方法 (function() { let div = document.createElement("div") div.innerHTML = "這是一輛ofo單車" document.getElementById("box").appendChild(div) })() }, Mobike: function() { .... }, ... }抽象工廠模式
抽象工廠模式:通過(guò)對(duì)類的工廠抽象使其業(yè)務(wù)用于對(duì)產(chǎn)品類簇的創(chuàng)建,而不負(fù)責(zé)創(chuàng)建某一類產(chǎn)品的實(shí)例。抽象類
在JavaScript中abstract是一個(gè)保留字,所以目前來(lái)說(shuō)還不能像傳統(tǒng)的面向?qū)ο笳Z(yǔ)言那樣輕松的創(chuàng)建抽象類。抽象類是一種聲明但不能使用的類,當(dāng)你使用時(shí)就會(huì)報(bào)錯(cuò)。
// 抽象類 let Car = function() {} Car.prototype = { run: function() { return new Error("抽象方法不能調(diào)用!") } }
// 在ES6中定義抽象類 class Car { constructor() { if (new.target === Car) { throw new Error ("抽象類不能實(shí)例化!") } } }
定義的Car中有一個(gè)run方法,繼承與Car的子類都會(huì)擁有直接使用,需要重寫。這也是抽象類的一個(gè)作用,即定義一個(gè)產(chǎn)品簇,并聲明一些必備的方法,如果子類中沒(méi)有重寫這些方法,直接使用就會(huì)拋出錯(cuò)誤。
抽象工廠var XMLHttpFactory = function() {} XMLHttpFactory.prototype = { // 如果真的要調(diào)用這個(gè)方法會(huì)拋出一個(gè)錯(cuò)誤,它不能被實(shí)例化,只能用來(lái)派生子類 createFactory: function () { throw new Error("This is an abstract class") } } // 經(jīng)典繼承 var XHRHandler = function () { XMLHttpFactory.call(this) } XHRHandler.prototype = new XMLHttpFactory() XHRHandler.prototype.constructor = XHRHandler XHRHandler.prototype.createFactory = function() { var XMLHttp = null; if(window.XMLHttpRequest) { XMLHttp = new XMLHttpRequest() } else if (window.ActiveXObject){ XMLHttp = new ActiveXObject("Microsoft.XMLHttp") } return XMLHttp; }
如果沒(méi)有看明白經(jīng)典繼承部分的代碼,可以去看看原型,原型鏈,call/apply。
用ES6的語(yǔ)法來(lái)實(shí)現(xiàn)一下抽象工廠,還是用共享單車的例子來(lái)改寫一下:
// 別較真 栗子不好吃 理解這種方式就行 class Bike { constructor(name) { if (new.target === Bike) { throw new Error("抽象類不能實(shí)例化!") } this.name = name; // ... 此處省略100行 } // ... 此處省略100行 init () { return new Error("抽象方法不能調(diào)用!") } } class Ofo extends Bike { constructor(name) { super("ofo") this.name = name; // ... 此處省略100行 } // ... 此處省略100行 init () { console.log("這是一輛ofo單車!") } } class Mobike extends Bike { ... } class Hello extends Bike { ... } class Blue extends Bike { ... } // ... 更多的單車 let Bikefactory = function (name) { switch (name) { case "Ofo": return new Ofo() break; case "Mobike": return new Mobike() break; case "Hello": return new Hello() break; case "Blue": return new Blue() break; } }
抽象工廠只留了一個(gè)“口子”,它不做具體的事,由它的子類,根據(jù)自身情況重寫方法。
最后創(chuàng)建了一個(gè)前端學(xué)習(xí)交流群,感興趣的朋友,一起來(lái)嗨呀!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/99541.html
摘要:官方解釋工廠是構(gòu)造方法的抽象,抽象了創(chuàng)建具體對(duì)象的過(guò)程。工廠方法模式的實(shí)質(zhì)是定義一個(gè)創(chuàng)建對(duì)象的接口,但讓實(shí)現(xiàn)這個(gè)接口的類來(lái)決定實(shí)例化哪個(gè)類。 前言 上一章回顧了JS對(duì)象的屬性類型,那么除了我們常用的new Object()構(gòu)造函數(shù)創(chuàng)建對(duì)象和字面量方式創(chuàng)建對(duì)象的方式外,還需要用到更多的模式來(lái)解決對(duì)象被多次復(fù)用的問(wèn)題。什么意思呢?就是我們很有可能會(huì)在各個(gè)地方去使用已經(jīng)創(chuàng)建過(guò)的對(duì)象,但是對(duì)象...
摘要:注意事項(xiàng)聲明函數(shù)時(shí)候處理業(yè)務(wù)邏輯區(qū)分和單例的區(qū)別,配合單例實(shí)現(xiàn)初始化構(gòu)造函數(shù)大寫字母開頭推薦注意的成本。簡(jiǎn)單工廠模式使用一個(gè)類通常為單體來(lái)生成實(shí)例。 @(書籍閱讀)[JavaScript, 設(shè)計(jì)模式] 常見(jiàn)設(shè)計(jì)模式 一直對(duì)設(shè)計(jì)模式不太懂,花了一下午加一晚上的時(shí)間,好好的看了看各種設(shè)計(jì)模式,并總結(jié)了一下。 設(shè)計(jì)模式簡(jiǎn)介 設(shè)計(jì)模式概念解讀 設(shè)計(jì)模式的發(fā)展與在JavaScript中的應(yīng)用 ...
摘要:集中實(shí)例化的函數(shù)第一個(gè)實(shí)例第二個(gè)實(shí)例工廠模式的分類工廠模式分為簡(jiǎn)單工廠抽象工廠和智能工廠,工廠模式不顯示地要求使用一個(gè)構(gòu)造函數(shù)。工廠模式之弊大多數(shù)類最好使用關(guān)鍵字和構(gòu)造函數(shù),可以讓代碼更加簡(jiǎn)單易讀。帶原型的構(gòu)造器中有一個(gè)名為的屬性。 什么是模式 前陣子準(zhǔn)備期末考試,挺累也挺忙的,實(shí)在閑不得空來(lái)更新文章,今天和大家說(shuō)說(shuō)javascript中的設(shè)計(jì)模式。 首先呢,我們需要知道的是:模式是一...
摘要:設(shè)計(jì)模式工廠模式最近閱讀了幾本設(shè)計(jì)模式方面的書籍學(xué)習(xí)之余整理下來(lái)方便以后的歸納和梳理設(shè)計(jì)模式工廠模式創(chuàng)造工廠模式是一種創(chuàng)建性模式也就是一種創(chuàng)建對(duì)象的最佳實(shí)踐首先我們需要理解為什么我們需要工廠模式想象一個(gè)場(chǎng)景如果你要求去買一些東西板燒雞腿 Javascript設(shè)計(jì)模式-工廠模式 最近閱讀了幾本設(shè)計(jì)模式方面的書籍,學(xué)習(xí)之余整理下來(lái),方便以后的歸納和梳理 設(shè)計(jì)模式-工廠模式 創(chuàng)造工廠模式是一...
摘要:依賴于接口的設(shè)計(jì)模式下面列出的設(shè)計(jì)模式,尤其依賴接口工廠模式。這些私用的靜態(tài)成員可以從構(gòu)造器內(nèi)部訪問(wèn),這意味著所有私用函數(shù)和特權(quán)函數(shù)都能訪問(wèn)它們。構(gòu)造器靜態(tài)特權(quán)方法封裝之弊私用方法很難進(jìn)行單元測(cè)試。 1.弱類型語(yǔ)言 在JavaScript中,定義變量時(shí)不必聲明其類型。但這并不意味著變量沒(méi)有類型。一個(gè)變量可以屬于幾種類型之一,這取決于其包含的數(shù)據(jù)。JavaScript中有三種原始類型:...
閱讀 2571·2021-09-26 10:13
閱讀 5969·2021-09-08 10:46
閱讀 685·2019-08-30 15:53
閱讀 2957·2019-08-29 16:13
閱讀 2750·2019-08-26 12:23
閱讀 3478·2019-08-26 11:24
閱讀 1085·2019-08-23 18:09
閱讀 1028·2019-08-23 17:08