js設計模式(上)

 

引用:(23條消息) 《Javascript設計模式與開發實踐》關於設計模式典型代碼的整理(上):單例模式、策略模式、代理模式、迭代器模式、發佈-訂閱模式、命令模式、組合模式_QQsilhonette的博客-CSDN博客

1、單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

使用閉包封裝私有變量
// 使用閉包創建單例
var user = (function () {
var _name = 'sven',
_age = 29;

return {
getUserInfo: function () {
return _name + '-' + _age;
}
}
})();
惰性單例(只在合適的時候創建對象,並且之創建唯一的一個,試用於dom重複生成、事件綁定等場景)
// 惰性單例生成
var getSingle = function (fn) {
var result;
return function () {
return result || (result = fn.apply(this, arguments));
}
};
2、策略模式:定義一系列的算法,把它們一個個封裝起來,並且使它們可以相互替換。

// 策略模式
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 strategies[level](salary);
}
// 測試
console.log(calculateBonus('S', 20000));
console.log(calculateBonus('A', 10000));
3、代理模式:爲一個對象提供一個代用品或佔位符,以便控制對它的訪問。

// 虛擬代理
var myImage = (function () {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);

return {
setSrc: function (src) {
imgNode.src = src;
}
}
})();

var proxyImage = (function () {
var img = new Image;
img.onload = function () {
myImage.setSrc(this.src);
}
return {
setSrc: function (src) {
myImage.setSrc('file:// /C:/Users/svenzeng/Desktop/loading.gif');
img.src = src;
}
}
})();
// 測試
proxyImage.setSrc('http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );
// 緩存代理
var mult = function () {
console.log('開始計算乘積');
var a = 1;
for(var i = 0, l = arguments.length; i < l; i++) {
a = a * arguments[i];
}
return a;
}

var proxyMult = (function () {
var cache = {};
return function () {
var args = Array.prototype.join.call(arguments, ',');
if(args in cache) {
return cache[args];
}
return cache[args] = mult.apply(this, arguments);
}
})();
// 測試
proxyMult(1,2,3,4);
proxyMult(1,2,3,4);

4、迭代器模式:提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內部表示。

// 迭代器模式
var each = function(ary, callback) {
for (var i = 0, l = ary.length; i < l; i++) {
callback.call(ary[i], i, ary[i]);
}
};
// 測試
each([1, 2, 3], function(i, n) {
alert ([i, n]);
});
5、發佈-訂閱模式:它定義對象間的一種一對多的依賴關係,當一個對象的狀 態發生改變時,所有依賴於它的對象都將得到通知。

// 發佈-訂閱模式
var event = {
clientList: [],
listen: function (key, fn) {
if (!this.clientList[key]) {
this.clientList[key] = [];
}
this.clientList[key].push(fn); // 訂閱的消息添加進緩存列表
},
trigger: function () {
var key = Array.prototype.shift.call(arguments);
fns = this.clientList[key];
if (!fns || fns.length === 0) { // 如果沒有綁定對應的消息
return false;
}
for (var i = 0, fn; fn = fns[i++];) {
fn.apply(this, arguments);
}
},
remove: function (key, fn) {
var fns = this.clientList[key];
if (!fns) { // 如果 key 對應的消息沒有被人訂閱,則直接返回
return false;
}
if (!fn) { // 如果沒有傳入具體的回調函數,表示需要取消 key 對應消息的所有訂閱
fns && (fns.length = 0);
} else {
for (var l = fns.length - 1; l >= 0; l--) {
var _fn = fns[l];
if (_fn ===fn) {
fns.splice(l, 1); // 刪除訂閱者的回調函數
}
}
}
}
};
// 安裝發佈—訂閱功能
var installEvent = function (obj) {
for (var i in event) {
obj[i] = event[i];
}
};
// 測試
var salesOffices = {};
installEvent( salesOffices );

salesOffices.listen( 'squareMeter88', fn1 = function( price ){
console.log( '價格= ' + price );
}); // 小明訂閱消息
salesOffices.listen( 'squareMeter88', fn2 = function( price ){
console.log( '價格= ' + price );
}); // 小紅訂閱消息
salesOffices.remove( 'squareMeter88', fn1 );
salesOffices.trigger( 'squareMeter88', 2000000 ); // 輸出:2000000

6、命令模式:用一種松耦合的方式來設計程序,使得請求發送者和請求接收者能夠消除彼此之間的耦合關係。

// 命令模式
var bindClick = function (button, func) {
button.onclick = func;
};

var MenuBar = {
refresh: function () {
console.log('刷新菜單界面');
}
};

var SubMenu = {
add: function () {
console.log('增加子菜單');
},
del: function () {
console.log('刪除子菜單');
}
};
// 測試
bindClick(button1, MenuBar.refresh);
bindClick(button2, SubMenu.add);
bindClick(button3, SubMenu.del);

7、組合模式:將對象組合成樹形結構,以表示“部分-整體”的層次結構。

// 組合模式
var closeDoorCommand = {
execute: function () {
console.log('關門');
}
};

var openPcCommand = {
execute: function () {
console.log('開電腦');
}
};
var openQQCommand = {
execute: function () {
console.log('登錄 QQ');
}
};

var MacroCommand = function () {
return {
commandsList: [],
add: function (command) {
this.commandsList.push(command);
},
execute: function () {
for (var i = 0, command; command = this.commandsList[i++];) {
command.execute();
}
}
}
};
// 測試
var macroCommand = MacroCommand();
macroCommand.add(closeDoorCommand);
macroCommand.add(openPcCommand);
macroCommand.add(openQQCommand);

macroCommand.execute();

————————————————
版權聲明:本文爲CSDN博主「QQsilhonette」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/QQsilhonette/article/details/84943932

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章