JS常用設計模式
大型單頁應用程式裡,複雜度上升到一定程度時,沒有適當的設計模式進行降耦,後續的開發也難以下手。
而設計模式正是為了降耦而存在。
單例模式
單例模式的核心是確保只有一個實例,並且提供全域存取。
特點
滿足「單一職責原則」 : 使用代理模式,不在建構函式中判斷是否已經創建過該單例;
滿足惰性原則
套用
彈出登陸視窗。
實例
var getSingle = function (fn) { var res; return function() { return res || (res = fn.apply(this, arguments)); } } var createPopup() { var p = document.createElement('p'); p.innerHTML = "Login window"; p.style.display = "none"; document.body.appendChild(p); return p; } var createLoginPopup = getSingle(createPopup); //create popup p here by using a given function, 满足两个原则 document.getElementById("loginBt").onclick = function() { var popup = createLoginPopup(); pop.style.display = "block"; }
建構子模式
/** * 构造一个动物的函数 */ function Animal(name, color){ this.name = name; this.color = color; this.getName = function(){ return this.name; } } // 实例一个对象 var cat = new Animal('猫', '白色'); console.log( cat.getName() );
原型模式
function Person(){ } Person.prototype.name = "bill"; Person.prototype.address = "GuangZhou"; Person.sayName = function (){ alert(this.name); } var person1 = new Person(); var person2 = new Person(); //测试代码 alert(person1.name); // bill alert(person2.name); // bill person1.sayName(); //bill person2.sayName(); //bill person1.name = "666"; alert(person1.name); // 666 alert(person2.name); // bill person1.sayName(); //666 person2.sayName(); //bill
混合模式
/** * 混合模式 = 原型模式 + 构造函数模式 */ function Animal(name, color){ this.name = name; this.color = color; console.log( this.name + this.color) } Animal.prototype.getInfo = function(){ console.log('名称:'+ this.name); } function largeCat(name, color){ Animal.call(null, name, color); this.color = color; } largeCat.prototype = create(Animal.prototype); function create (parentObj){ function F(){} F.prototype = parentObj; return new F(); }; largeCat.prototype.getColor = function(){ return this.color; } var cat = new largeCat("Persian", "白色"); console.log( cat )
工廠模式
#工廠:函數內部產生b物件並回傳。
1. function a(name){ var b = new object(); b.name = name; b.say = function(){ alert(this.name); } return b } 2. function Animal(opts){ var obj = new Object(); obj.name = opts.name; obj.color = opts.color; obj.getInfo = function(){ return '名称:'+obj.name +', 颜色:'+ obj.color; } return obj; } var cat = Animal({name: '波斯猫', color: '白色'}); cat.getInfo();
簡單工廠模式
簡單工廠模式的概念就是創建對象,對不同類的實例化;只需要創建一個對象,然後透過對這個對像大量的方法和屬性,並在最終將物件返回出來
//basketball base class var Baseketball = function(){ this.intro = 'baseketball is hotting at unitedstates'; } Baseketball.prototype = { getMember : function(){\ console.log('each team needs five players'); }, getBallSize : function(){ console.log('basketball is big'); } } //football base class var Football = function(){ this.intro = 'football is popular at all of the world'; } Football = function(){ getMember = function(){ }, getBallSize = function(){ } } //sport factory var SportsFactory = function(name){ switch(name){ case 'NBA': return new Baseketball(); case 'wordCup': return new Football(); } } //when you want football var football = SportsFactory('wordCup'); console.log(football); console.log(football.intro); football.getMember();
迭代器模式
#裝飾者模式
#策略模式
定義一個可以互相替換的演算法,並且把他們封裝起來。
特點
符合開放-封閉原則: 要修改使用的演算法時不用深入函數內部進行修改,只需修改策略類別;
#將演算法的實作與使用分離開,提高演算法復用性;
#透過組合、委託和多態避免多重條件選擇語句;
#應用程式
動畫實現不同的緩動效果。
一般分為兩個部分:策略類別於環境類別。策略類別用於封裝各種演算法,並且負責具體的計算過程; 環境類別負責接收使用者的請求,並且把請求委託給某一個策略類別。因為各個策略類別實現的演算法和計算的結果不同,而環境類別呼叫策略類別的方法卻是相同的,這就體現了多態性。要實作不同的演算法,只需要替換環境類別中的策略類別即可。
在js中,我們不必建構策略類,可直接使用函數作為策略物件。
範例
var strategies = { "s1": function() { //algo 1 }, "s2": function() { //algo 2 }, "s3": function() { //algo 3 } } var someContext = new SomeConext(); someContext.start("s1"); //using s1 to calculate //someContext.add("s1"); or add s1 as a rule for validation
外觀模式
也可翻譯為門面模式。它為子系統中的一組接口提供一個一致的介面, Facade模式定義了一個高層接口,這個接口使得這個子系統更加容易使用。在引入外觀角色之後,使用者只需要直接與外觀角色交互,使用者與子系統之間的複雜關係由外觀角色來實現,從而降低了系統的耦合度。
例如在家要看電影,需要打開音響,再打開投影儀,再打開播放器等等,引入外觀角色之後,只需要調用“打開電影設備”方法就可以。外觀角色封裝了開啟投影機等操作,提供使用者更容易使用的方法。
作用
簡化複雜介面
#解耦和,屏蔽使用者對子系統的直接存取
#實例
在形式上,外觀模式在javascript中就像這樣:
function a(x){ // do something } function b(y){ // do something } function ab( x, y ){ a(x); b(y); }
下面的一個例子,把阻止冒泡和阻止預設事件放到了外觀角色:
var N = window.N || {}; N.tools = { stopPropagation : function( e ){ if( e.stopPropagation ){ e.stopPropagation(); }else{ e.cancelBubble = true; } }, preventDefault : function( e ){ if( e.preventDefault ){ e.preventDefault(); }else{ e.returnValue = false; } }, stopEvent : function( e ){ N.tools.stopPropagation( e ); N.tools.preventDefault( e ); }
外觀模式在javascript的應用主要可以分為兩類,某塊程式碼反覆出現,例如函數a的呼叫基本上都出現在函數b的呼叫之前,那麼可以考慮考慮將這塊程式碼使用外觀角色包裝來優化結構。還有一種就是對於一些瀏覽器不相容的API,放置在外觀內部進行判斷,處理這些問題最好的方式便是將跨瀏覽器差異全部集中放置到一個外觀模式實例中來提供一個對外接口。
代理模式
代理模式的定義:為其他物件提供一種代理以控制對這個物件的存取。在某些情況下,一個對像不適合或不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
虛擬代理
虛擬代理程式是把一些開銷很大的對象,延遲到真正需要它的時候才去創建執行
圖片懶加載
//图片加载 let imageEle = (function(){ let node = document.createElement('img'); document.body.appendChild(node); return { setSrc:function(src){ node.src = src; } } })(); //代理对象 let proxy = (function(){ let img = new Image(); img.onload = function(){ imageEle.setSrc(this.src); }; return { setSrc:function(src){ img.src = src; imageEle.setSrc('loading.gif'); } } })(); proxy.setSrc('example.png');
合併http請求
如果有一個功能需要頻繁進行請求操作,這樣開銷比較大,可以透過一個代理函數收集一段時間內請求數據,一次發出
//上传请求 let upload = function(ids){ $.ajax({ data: { id:ids } }) } //代理合并请求 let proxy = (function(){ let cache = [], timer = null; return function(id){ cache[cache.length] = id; if(timer) return false; timer = setTimeout(function(){ upload(cache.join(',')); clearTimeout(timer); timer = null; cache = []; },2000); } })(); // 绑定点击事件 let checkbox = document.getElementsByTagName( "input" ); for(var i= 0, c; c = checkbox[i++];){ c.onclick = function(){ if(this.checked === true){ proxy(this.id); } } }
快取代理
快取代理可以作為一些開銷大的運算結果提供暫時的存儲,下次運算時,如果傳遞進來的參數跟之前一致,則可以直接返回前面存儲的運算結果
//计算乘积 let mult = function(){ let result = 1; for(let i = 0,len = arguments.length;i < len;i++){ result*= arguments[i]; } return result; } //缓存代理 let proxy = (function(){ let cache = {}; reutrn function(){ let args = Array.prototype.join.call(arguments,','); if(args in cache){ return cache[args]; } return cache[args] = mult.apply(this,arguments); } })();
優缺點
1.優點:代理模式能將代理物件與被呼叫物件分離,降低了系統的耦合度。代理模式在客戶端和目標物件之間起到一個中介作用,這樣可以起到保護目標對象的作用。代理物件也可以對目標物件呼叫之前進行其他操作。
2.缺點:增加了系統的複雜度
觀察者模式
模組模式
/** * 模块模式 = 封装大部分代码,只暴露必需接口 */ var Car = (function(){ var name = '法拉利'; function sayName(){ console.log( name ); } function getColor(name){ console.log( name ); } return { name: sayName, color: getColor } })(); Car.name(); Car.color('红色');
相關推薦:
以上是JS常用設計模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在Java框架中,設計模式和架構模式的區別在於:設計模式定義了在軟體設計中解決常見問題的抽象解決方案,專注於類別和物件之間的交互,例如工廠模式。架構模式定義了系統結構和模組之間的關係,關注系統元件的組織和交互,如分層架構。

裝飾器模式是一種結構型設計模式,允許動態添加物件功能,無需修改原始類別。它透過抽象組件、具體組件、抽象裝飾器和具體裝飾器的協作實現,可以靈活擴展類別功能,滿足變化的需求。範例中,將牛奶和摩卡裝飾器添加到Espresso,總價為2.29美元,展示了裝飾器模式在動態修改物件行為方面的強大功能。

1.工廠模式:分離物件創建和業務邏輯,透過工廠類別建立指定類型的物件。 2.觀察者模式:允許主題物件通知觀察者物件其狀態更改,實現鬆散耦合和觀察者模式。

設計模式透過提供可重複使用和可擴展的解決方案來解決程式碼維護難題:觀察者模式:允許物件訂閱事件,並在事件發生時收到通知。工廠模式:提供了一種創建物件的集中式方式,而無需依賴特定類別。單例模式:確保一個類別只有一個實例,用於建立全域可存取的物件。

TDD用於編寫高品質PHP程式碼,步驟包括:編寫測試案例,描述預期功能並使其失敗。編寫程式碼,僅使測試案例通過,無需過度優化或詳細設計。測試案例通過後,優化和重構程式碼以提高可讀性、可維護性和可擴展性。

適配器模式是一種結構型設計模式,允許不相容物件協同工作,它將一個介面轉換為另一個,使物件能夠順利互動。物件適配器透過建立包含被適配器對象的適配器對象,並實現目標接口,實現適配器模式。在一個實戰案例中,透過適配器模式,客戶端(如MediaPlayer)可以播放高級格式的媒體(如VLC),儘管本身僅支援普通媒體格式(如MP3)。

Guice框架應用了多項設計模式,包括:單例模式:透過@Singleton註解確保類別只有一個實例。工廠方法模式:透過@Provides註解建立工廠方法,在依賴注入時取得物件實例。策略模式:將演算法封裝成不同策略類,透過@Named註解指定具體策略。

Java框架中使用設計模式的優點包括:程式碼可讀性、可維護性和可擴充性增強。缺點包括:過度使用導致複雜性、效能開銷以及學習曲線陡峭。實戰案例:代理模式用於延遲載入物件。明智地使用設計模式可充分利用其優勢並最小化缺點。
