綜述:基於javascript設計模式與開發實踐(曾探著)一書所寫,算是學習筆記吧,16種常見設計模式簡述。先將設計模式的概念講清楚,便於初學者學習,代碼很基礎,有一個概念很重要。
示例代碼下載鏈接:http://www.ituring.com.cn/book/1632 ---隨書下載
1.設計模式的概念和設計原則
1.1設計模式的概念
設計模式一套被反覆使用、思想成熟、經過分類和無數實戰設計經驗總結的。使用設計模式是爲了讓系統代碼可複用、可擴展、可解耦、更容易被人理解且能保證代碼可靠性。設計模式是代碼真正工程化;設計模式是軟件工程的基石脈絡;如同大廈的結構一樣。只有夯實地基結構,才能蓋好健壯的大樓。也是我們邁向高級開發人員必經的一步;JavaScript是一門特別靈活的語言,早些年被認爲是玩具式的語言,只能做一點爲網頁塗脂抹粉的小事。項目工程也不是很大,更無從說起設計模式在JavaScript的應用,但隨着nodejs以及H5和web2.0的興起,JavaScript變得越來越受重視。
1.2設計模式的原則
設計模式存在的根本原因是爲了代碼的複用;增加可維護性。如下原則:
- 開閉原則:對擴展開放,對修改關閉。
- 里氏轉換原則:子類繼承父類,單獨拿出來完全可以運行;
- 依賴倒轉原則:引用一個對象,如果這個對象有底層類型,直接引用底層;
- 接口隔離原則:每一個接口應該是一個角色;
- 和成/聚合複用原則:新的對象應使用一些已有的對象,使之成爲新的對象的一部分;
- 迪米特原則:一個對象應對其他對象有儘可能少的瞭解;
2.十六種設計模式介紹
2.1 單例模式
在JavaScript裏,實現單例的方式有很多種,其中最簡單的一個方式是使用對象字面量的方法,其字面量裏可以包含大量的屬性和方法,減少了全局變量,避免了命名空間的污染。在開發中十分常用,第一次組織代碼的方式就是使用單例模式組織代碼的;
//單例模式示例
var mySingleton={
property1:"something",
property2:"songthing else",
method1:funciton(){
console.log("hello world");
}
}
2.2 策略模式
策略模式指的是定義一系列的算法,把他們一個個封裝起來,並且使他們可以互相替換。多用來處理if 、else if的頁面邏輯;比如根據評價等級和工資水平來計算年終獎問題。
//代理模式示例
var strategies={
"S":function(salary){
return salary *4;
},
"A":function(salary){
return salary *3;
},
"B":function(salary){
return salary * 2;
}
}
var calculateBonus=function(level,salary){
return stragegies[level](salary);
}
console.log(calculateBonus("S",20000)); //80000
console.log(calculateBonus("A",10000)); //30000
2.3 代理模式
2.3.1保護代理
2.3.2虛擬代理
2.3.3 緩存代理(這個問題在明源雲的面試問題中有涉及,非常的有用)
緩存代理可以爲一些開銷大的運算結果提供暫時的存儲,在下次運算時,如果傳遞進來的參數跟之前一致,則直接返回前面存儲的運算結果。
/**************** 計算乘積 *****************/
var mult = function(){
var a = 1;
for ( var i = 0, l = arguments.length; i < l; i++ ){
a = a * arguments[i];
}
return a;
};
/**************** 計算加和 *****************/
var plus = function(){
var a = 0;
for ( var i = 0, l = arguments.length; i < l; i++ ){
a = a + arguments[i];
}
return a;
};
/**************** 創建緩存代理的工廠 *****************/
var createProxyFactory = function( fn ){
var cache = {};
return function(){
var args = Array.prototype.join.call( arguments, ',' );
if ( args in cache ){
return cache[ args ];
}
return cache[ args ] = fn.apply( this, arguments );
}
};
var proxyMult = createProxyFactory( mult ),
proxyPlus = createProxyFactory( plus );
alert ( proxyMult( 1, 2, 3, 4 ) ); // 輸出:24
alert ( proxyMult( 1, 2, 3, 4 ) ); // 輸出:24
alert ( proxyPlus( 1, 2, 3, 4 ) ); // 輸出:10
alert ( proxyPlus( 1, 2, 3, 4 ) ); // 輸出:10
2.4 迭代器模式
2.5 發佈-訂閱模式(也叫作觀察者模式,這是一個十分重要的設計模式,在工作中用的特別多,Vue的源碼中主要使用了發佈訂閱者模式和代理模式),在lazyMan中也有大量的考察。
var salesOffices={};
salesOffices.clientList=[];
salesOffices.listen=function(fn){
this.clientList.push(fn); //將訂閱的消息添加到緩存列表,按照隊列的方式來分別執行相應的執行模塊
};
salesOffices.trigger=function(){
for(var i=0,fn;fn=this.clientList[i++];){
fn.apply(this,arguments); //循環調用緩存隊列中的函數
}
};
//定義第一個處理函數
salesOffices.listen(function(prices,squarMeter){
setTimeout(function(){
console.log("產品價格是:"+prices,"房屋面積是:"+squarMeter);
},3000);
});
//定義第二個處理函數
salesOffices.listen(function(prices,squarMeter){
console.log("產品價格是666:"+prices,"房屋面積是6666:"+squarMeter);
});
//以下還可以定義多個其他函數
salesOffices.trigger(3000,20); //傳入參數,按照順序執行相應的函數,從上往下執行
2.6 命令模式
2.7 組合模式
2.8 模板方法模式
2.9 享元模式
2.10 職責鏈模式
2.11 中介者模式
2.12 裝飾者模式
2.13 狀態模式
2.14 適配器模式
3.設計原則和編程技巧
3.1 單一職責原則
3.2 最少知識原則
3.3 開放-封閉原則
3.4 接口和麪向接口編程
4.代碼重構的建議
---未完待續