首先須要說一下工廠模式。工廠模式根據抽象程度的不一樣分爲三種數據庫
簡單工廠模式:又稱爲靜態工廠方法模式,它屬於類建立型模式。
在簡單工廠模式中,能夠根據參數的不一樣返回不一樣類的實例。
由工廠對象決定建立某一種產品對象類的實例。緩存
// #簡單工廠模式第一種 /** * 足球類 */ var FootBall = function () { this.play = function () { console.log('我在踢足球'); } } /** * 籃球類 */ var BasketBall = function () { this.play = function () { console.log('我在打籃球'); } } var football = new FootBall(); football.play(); var basketball = new BasketBall(); basketball.play(); /** * 球類工廠 */ var Ball = function(name) { switch (name) { case '足球': return new FootBall(); break; case '籃球': return new BasketBall(); break; } } var football = Ball('足球'); football.play(); var basketball = Ball('籃球'); basketball.play(); // #簡單工廠模式第一種end
這段案例能夠簡單的這麼去理解,假設咱們須要多個球,咱們但願在使用球的時候,只須要告訴管理員咱們須要的球的類型,不須要一個個去找對應的球這個管理員就相對於工廠函數。安全
簡單講就是使用簡單工廠模式,那麼你就不須要關心它的具體實現,你只須要知道你要使用的類型,那麼工廠函數會自動幫你去作對應的事情函數
// #簡單工廠模式第二種 /** * 球類工廠 */ var Ball = function(name) { // 建立一個對象,對對象擴展擴展屬性還有方法 var o = new Object(); o.name = name; //默認的方法 若是在加上一個羽毛球類,這時候就不須要補充play方法 o.play = function () { console.log('我在打'+name); } if (name === '足球') { o.play = function () { console.log('我在踢'+name); } }else if (name === '籃球') { o.play = function () { console.log('我在打'+name); } } // 將對象返回 return o; } var football = Ball('足球'); football.play(); var basketball = Ball('籃球'); basketball.play(); // #簡單工廠模式第二種end
這段案例是用對象的方式代替多個類,把相同點抽離出來,this
不一樣點在一一作類型判斷,這樣也是簡單工廠模式實現的另外一種方式prototype
簡單工廠模式的優勢:設計
簡單工廠模式的缺點code
簡單工廠模式的適用狀況對象
在如下狀況下可使用簡單工廠模式:繼承
簡單工廠模式總結
工廠方法模式:又稱爲工廠模式,也叫虛擬構造器模式或者多態工廠模式它屬於類建立型模式。在工廠方法模式中,工廠父類負責定義建立產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣作的目的是將產品類的實例化操做延遲到工廠子類中完成,即經過工廠子類來肯定究竟應該實例化哪個具體產品類這樣解釋可能會有點抽象。
// # 工廠方法模式 // 安全模式建立工廠類 var Ball = function (type,name) { /** * 安全模式 Ball也能夠運行處new Ball的效果 */ if(this instanceof Ball) { var s = new this[type](name); return s; }else { return new Ball(type,name); } } // 工廠原型中設置建立全部類型數據對象的基類 Ball.prototype = { basketBall: function(name) { this.play = function() { console.log('我在打'+name); } }, footBall: function(name) { this.play = function() { console.log('我在踢'+name); } }, badmintonBall: function(name) { this.play = function() { console.log('我在打'+name); } }, // .... } var football = new Ball('footBall','足球'); football.play(); var basketball = new Ball('basketBall','籃球'); basketball.play(); var badmintonball = new Ball('badmintonBall','羽毛球'); badmintonball.play(); // # 工廠方法模式end
這段案例是這麼去理解的,咱們先建立一個球類工廠,這個球類工廠是一個抽象的,不作具體的實現,而後咱們在這個球類工廠裏面在去定義對應的球類實現,如籃球,羽毛球,足球等實現,在工廠方法模式中,抽象類工廠只是負責定義一個對外的公共接口,而工廠子類則負責生成具體的產品對象。
這樣作的目的是將產品類的實例化操做延遲到工廠子類中完成,即經過工廠子類來肯定究竟應該實例化哪個具體產品類若是這時候在出現一個新的球類運動,只須要爲這種新類型的球類建立一個具體的球類實現就能夠,這一特色無疑使得工廠方法模式具備超越簡單工廠模式的優越性,更加符合「開閉原則」
上面案例包含了一個安全模式的知識點
// 安全模式建立工廠類 var Ball = function (type,name) { /** * 安全模式 Ball也能夠運行處new Ball的效果 */ if(this instanceof Ball) { var s = new this[type](name); return s; }else { return new Ball(type,name); } }
這段代碼主要解決的問題是,有些同窗使用工廠類的時候,忘記使用關鍵字new,得不到預期想要的效果這邊的解決方案就是,在構造函數開始時先判斷當前對象this指代是否是當前工廠類,若是不是則經過new關鍵字建立對象返回,這樣就能夠實現不使用new關鍵詞也能夠達到相同的效果了
工廠方法模式的優勢:
工廠方法模式的缺點:
工廠方法模式的適用狀況
在如下狀況下可使用工廠方法模式:
工廠方法模式總結
工廠方法模式是簡單工廠模式的進一步抽象和推廣。因爲使用了面向對象的多態性,工廠方法模式保持了簡單工廠模式的優勢,並且克服了它的缺點。在工廠方法模式中,核心的工廠類再也不負責全部產品的建立,而是將具體建立工做交給子類去作。這個核心類僅僅負責給出具體工廠必須實現的接口,而不負責產品類被實例化這種細節,這使得工廠方法模式能夠容許系統在不修改工廠角色的狀況下引進新產品。
工廠方法模式的主要優勢是增長新的產品類時無須修改現有系統,並封裝了產品對象的建立細節,系統具備良好的靈活性和可擴展性;其缺點在於增長新產品的同時須要增長新的工廠,致使系統類的個數成對增長,在必定程度上增長了系統的複雜性。
抽象工廠模式:經過對類的工廠抽象使其業務用於對產品類簇的建立,而不是負責建立某一類產品的實例,屬於對象建立型模式。
抽象類一直出如今咱們的文章中,那麼這邊先來解釋一下什麼是抽象類
抽象類是一種聲明但不能使用的類,當你使用時就會報錯,在JavaScript中abstract仍是一個保留字,因此目前來講還不能像
傳統面嚮對象語言那麼輕鬆的去建立抽象類.
不過JavaScript有本身的實現方式,能夠模擬出抽象類
來一段代碼
// 抽象類的介紹 var Ball = function () {} Ball.prototype = { play: function () { return new Error('抽象方法不能調用'); } }
解釋:
咱們能夠看到建立的Ball類其實什麼都不能作,建立時沒有任何屬性,原型定義的方法也不能使用,不然就會報錯。可是在繼承上倒是頗有用的,
由於定義了一種類,並定義了該類所具有的方法,若是沒有在子類中重寫這寫方法,那麼調用的時候就會報錯。
這一特色能夠很好的提醒子類去重寫這一方法,否則會在調用的時候提示錯誤那麼在瞭解了什麼是抽象類的狀況下,咱們在來比較一下工廠方法模式與抽象工廠模式的不一樣點,以方便咱們更好的去理解抽象工廠模式
工廠方法模式與抽象工廠模式的對比
在工廠方法模式中具體工廠負責生產具體的產品,每個具體工廠對應一種具體產品,工廠方法也具備惟一性,通常狀況下,一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。可是有時候咱們須要一個工廠能夠提供多個產品對象,而不是單一的產品對象。
爲了更清晰地理解抽象工廠模式,須要先引入兩個概念:
海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中。
抽象工廠模式與工廠方法模式最大的區別在於,工廠方法模式針對的是一個產品等級結構,而抽象工廠模式則須要面對多個產品等級結構,一個工廠等級結構能夠負責多個不一樣產品等級結構中的產品對象的建立。當一個工廠等級結構能夠建立出分屬於不一樣產品等級結構的一個產品族中的全部對象時,抽象工廠模式比工廠方法模式更爲簡單、有效率。
這句話比較簡單的理解方式就是:若是一個工廠只須要生產一個類型的產品好比說電視機,那麼用工廠方法模式是比較合理的,若是這個工廠又須要成產電視機,又須要生產冰箱之類的,那麼這時候用工廠抽象模式就是最合適的。
// # 抽象工廠模式 var Sport = function(subType, superType) { if( typeof Sport[superType] === 'function'){ // 緩存類 function F() {}; // 繼承父類屬性和方法 F.prototype = new Sport[superType](); // 將子類constructor 指向子類 subType.constructor = subType; // 子類原型繼承 「父類」 subType.prototype = new F(); }else { // 不存在抽象類則拋出錯誤 throw new Error('未建立該抽象類'); } } // 球類運動抽象類 Sport.Ball = function () { this.type = 'ball'; } Sport.Ball.prototype = { play: function () { return new Error('抽象方法不能調用'); } } // 力量型運動抽象類 Sport.Power = function () { this.type = 'power'; } Sport.Power.prototype = { play: function () { return new Error('抽象方法不能調用'); } } // 速度型運動抽象類 Sport.Speed = function () { this.type = 'speed'; } Sport.Speed.prototype = { play: function () { return new Error('抽象方法不能調用'); } } // 籃球類 var BasketBall = function (name) { this.name = name; }; // 抽象工廠實現對球類運動的繼承 Sport(BasketBall,'Ball'); BasketBall.prototype.play = function () { console.log('我在玩'+this.name); } // 舉重類 var WeightLifting = function (name) { this.name = name; }; // 抽象工廠實現對力量型運動的繼承 Sport(WeightLifting,'Power'); WeightLifting.prototype.play = function () { console.log('我在玩'+this.name); } // 跑步類 var Running = function (name) { this.name = name; }; // 抽象工廠實現對速度運動的繼承 Sport(Running,'Speed'); Running.prototype.play = function () { console.log('我在'+this.name); } // 抽象工廠模式實現 var basketBall = new BasketBall('籃球'); console.log(basketBall.type);//ball basketBall.play(); var weightLifting = new WeightLifting('舉重'); console.log(weightLifting.type);//power weightLifting.play(); var running = new Running('跑步'); console.log(running.type);//ball running.play(); /** 輸出結果 * ball * 我在玩籃球 * power * 我在玩舉重 * speed * 我在跑步 */ // # 抽象工廠模式end
這段栗子先是建立一個運動類的抽象工廠,經過這個暴露外部調用的接口,傳遞2個參數,一個是subType,當前實例化的對象,也就是子類,
一個是superType,須要繼承的父類(抽象類)的名稱,在工廠函數中實現了子類對父類的繼承。
在繼承過程當中有一個地方須要注意,就是在對過渡類繼承的時候,咱們不是繼承父類原型,而是經過new關鍵字複製父類的一個實列,這樣作的目的是過渡類不只僅繼承父類的原型方法,還須要繼承父類的對象屬性,因此經過new關鍵字的方式實現了繼承。
而後經過在抽象工廠類上面進行擴展對應的抽象類,也就是咱們須要經過繼承的父類,我這邊添加了3個抽象類Ball,Power,Speed,分別給抽象類指定了type屬性,還有方法play,既然建立了抽象類,那麼下面就是開始使用抽象工廠去建立子類,這邊分別對Ball,Power,Speed 3個抽象類進行了實現建立了BasketBall(球類),WeightLifting(力量),Running(速度)3個子類3個子類分別對play方法進行了實現最後就是對於子類的調用實現,在實現子類調用的時候,
咱們能夠獲取到繼承的父類當中對應的type
抽象工廠模式的優勢:
當一個產品族中的多個對象被設計成一塊兒工做時,它可以保證客戶端始終只使用同一個產品族中的對象。
增長新的具體工廠和產品族很方便,無須修改已有系統,符合「開閉原則」。
抽象工廠模式的缺點:
開閉原則的傾斜性(增長新的工廠和產品族容易,增長新的產品等級結構麻煩)。
增長新的產品等級結構:對於增長新的產品等級結構,須要修改全部的工廠角色,包括抽象工廠類,在全部的工廠類中都須要增長生產新產品的方法,不能很好地支持「開閉原則」。
抽象工廠模式的適用狀況:
在如下狀況下可使用抽象工廠模式:
抽象工廠模式總結
注:根據實際適用狀況去選擇對應的工廠模式