js設計模式有很多種,知道不代表會用,更不代表理解,為了更好的理解每個設計模式,對每個設計模式進行總結,以后只要看到總結,就能知道該設計模式的作用,以及模式存在的優缺點,使用范圍。
本文主要參考張容銘著的《JavaScript設計模式》。
1、簡單工廠模式
由一個工廠對象決定創建某一種產品對象類的實例,主要用來創建同一類對象。
舉例子:1、比如不同的彈出框,有警告框,提示框,確認框等。我們創建一個大類包含包含其共有的部分,比如顯示,內容等,再根據創建是選擇的類型,再將差異部分添加進去。
2、體育店里面有很多商品,及相關介紹,我們要買的時候,只要體育店有,就會得到相關產品和信息。先創建不同產品的基類,然后再用一個大類(也就是所謂的工廠)來包容這些基類。可用switch來選擇確定要創建什么。
總結:第一種是通過創建一個新對象然后包裝增強其屬性和功能實現的。第二種是通過類的實例化實現的。前一種因為共享父類,所以父類的方法方法屬性是可以共用的,后者就不行了。簡單工廠模式使用場合通常也限制在創建單一對象。
2、工廠方法模式
工廠方法模式:通過對產品類的抽象使其創建業務主要負責用於創建多類產品的實例。將實際創對象工作推遲到子類中,這樣核心類就成了抽象類。
其中涉及到一個安全模式類:
var demo = function(){ if(!(this instanceof demo)){ return new demo(); } }
通過判斷this是不是實例來進行實例化。這樣就可以避免漏掉new關鍵字。
var Factory=function(type,content){ if(this instanceof Factory){ var s=new this[type](content); }else{ return new Factory(type,content) } } Factory.prototype={ java:function(content){ //...... }, php:function(content){ //...... }, //...... }
在原型上添加不同類型的方法,然后在調用子類的時候實例化。如果采用簡單工廠模式的話,用類實例化方法,但是這樣需要修改工廠方法和添加基類,也就是要修改兩個地方。而采用上面的方法,只需要在原型上添加方法就可以了。
避免了使用者和對象類之間的耦合,用戶不用關心創建該類的具體類,只需要調用工廠方法就可以。
3、抽象工廠模式
抽象類並不是用來創建具體的類,而是用來當做父類來創建一些子類。創建的是一個類簇,它制定了類的結構。其實就是先創建一個大類,然后在細分下,添加小類的實現方法,將小類的方法掛到小類的原型上。
4、建造者模式
將一個復雜對象的構建層與其表示層相互分離,同樣的構建過程可采用不同的表示。
工廠模式主要是為了創建對象實例或者類簇(抽象工廠),關心的是最終產出(創建)的是什么。不關心創建的過程,僅僅需要創建的最終結果。所以工廠模式得到的是對象實例或者類簇。而建造者模式再創建對象的時候更為復雜,雖然其目的也是創建對象,但是其更多的是關心創建的整個過程,甚至於創建對象的每一個細節,比如創建一個人,我們不僅要得到人的實例,還要關心穿什么衣服,男的女的,興趣愛好等等。
舉例子:創建一個求職者。我們先創建三個類,Human,Named,Work類。然后在建造者類中調用這三個類的組合,創建一個完整的應聘者對象。
var Person=function(name,work){ var _person=new Human(); _person.name=new Named(name); _person.work=new Work(work); return _person; }
在建造者模式中將創建的對象類模塊化,這樣使得每個模塊都可以得到靈活的運用與高質量的復用。但是如果對象粒度很小,或者模塊間復用率很低且變動不大,我們最好還是創建整體對象。
5、原型模式
用原型實例指向創建者對象的類,使用於創建新的對象的類共享原型對象的屬性以及方法。
原型拓展:就是在prototype上進行拓展。
6、單例模式
只允許實例化對象一次。,有時我們也用一個對象來規划一個命名空間,井井有條的管理對象上的屬性和方法。
var sing=(function(){ var instance=null; function Single(){} return function(){ if(!instance){ instance=Single; } return instance; } })();
7、外觀模式
//外觀模式:為一組復雜的子系統接口提供一個更高級的統一接口,通過這個接口使得對子系統接口的訪問更加容易。在JavaScript中,有時也會用於對底層結構兼容性做統一封裝來簡化用戶使用。 //實現 function addEvent(dom,type,fn){ if(dom.addEventListener){ dom.addEventListener(type,fn,false); }else if(dom.attachEvent){ dom.attachEvent("on"+type,fn); }else{ dom["on"+type]=fn; } }
8、適配器模式
//適配器模式:將一個類(對象)的接口(方法或者屬性)轉化為另一個接口,以滿足用戶的需求,使類之間的接口的不兼容問題通過適配器得以解決。 //舉例子:其實就是為了兩個代碼庫所寫的代碼兼容運行而書寫的額外代碼。這樣我們就不需要特意地重寫以前的功能代碼了。 //參數適配器:比如某個函數要傳入很多參數 function dosomething(name,title,age,color,size,prize){}; //那么我們要記住這些參數的順序是很困難的,因此常用的做法是以一個參數對象方式傳入的。 function dosomething(obj){}; //即使這樣,還是存在一個問題,就是我們不知道參數是不是完整的,如果一些參數沒有傳入,需要使用默認值等等。此時我們通常的做法就是用適配器來適配傳入的這個參數對象。 function dosomething(obj){ var _adapter={ name:"me", title:"設計", age:24, color:"pink", } }