設(shè)計(jì)模式-策略模式
公司的年終獎(jiǎng)是根據(jù)工資基數(shù)和績(jī)效來(lái)發(fā)放的。例如績(jī)效為S的員工有4倍工資。A的員工有3倍工資。B的員工有2倍工資。
基本設(shè)計(jì):
function B(salary,level){
if('S' === level){
return 4*salary;
}else if('A' === level){
return 3*salary
}else if('B' === level){
return 2*salary
}
}
缺點(diǎn):不利于進(jìn)一步去拓展功能,比較危險(xiǎn):把核心代碼全部暴露在外面。
改進(jìn):
function PerS(salary){
return 4*salary;
}
function perA(salary){
return 3*salary;
}
function perB(salary){
return 2*salary;
}
var Obj = {
S : perS,
A: perA,
B:perB
}
function B(salary,level){
return Obj[level](salary);
}
好處:函數(shù)可以重復(fù)使用。
算法的使用和算法的實(shí)現(xiàn)分開(kāi)。
設(shè)計(jì)模式-裝飾者模式
裝飾模式,也可以稱為包裝器,就是對(duì)某個(gè)對(duì)象進(jìn)行再加工、使之功能增強(qiáng)的一種做法。
先把自己保存一個(gè)備份,再改寫自己。典型的例子jquery的ready函數(shù)。
function ready(func){
var _onload = typeof window.onload == "function" ? window.onload : function(){};
window.onload = function(){
_onload();
func();
}
}
將window.onload函數(shù)進(jìn)行改寫,先將原有的onload函數(shù)保存,然后再添加用戶自定義的方法。
設(shè)計(jì)模式-單例模式
構(gòu)造器只能創(chuàng)建一個(gè)對(duì)象。當(dāng)你再次去創(chuàng)建時(shí),它會(huì)把那個(gè)已經(jīng)創(chuàng)建好對(duì)象返回給你。而不是去另一個(gè)新的對(duì)象。
function Single(name){
this.name = name
}
Single.instance = null;
Single.get = function(name){
if(!Single.instance){
Single.instance = new Single(name);
return Single.instance
}else{
return Single.instance
}
}
var s1 = Single.get('s1')
var s2 = Single.get('s2')
s1 === s2 //true
缺點(diǎn):是必須要用get方法,如果是直接使用new就失去單例的特征。
var S = (function (){
var instance = null;
function Single(name){
if(instance){
return instance
}
this.name = name;
return instance = this;
}
return Single;
})()
var s1 = new S('s1');
var s2 = new S('s2');
設(shè)計(jì)模式-觀察者模式
顧名思義,就是訂閱某些功能,然后在適當(dāng)?shù)臅r(shí)機(jī)發(fā)布出來(lái),也就是執(zhí)行這些功能。
訂閱,就是把幾個(gè)函數(shù)推入數(shù)組中待用;
發(fā)布,就是把緩存在數(shù)組中的那一坨函數(shù)列隊(duì)執(zhí)行
var event = {
eventList:{},
listen:function(key,fn){
if(!this.eventList[key]){
this.eventList[key] = [];
}
this.eventList[key].push(fn);
},
remove:function(key,fn){
var fns = this.eventList[key];
if(!fns){
return false;
}
if(!fn){
//如果沒(méi)有回調(diào),表示取消此key下所有方法
fns && (fns.length=0);//這是一種快速清空數(shù)組的方法哦!
}else{
for(var i=0;i<fns.length;i++){
//遍歷方法列表,剔除需要取消的方法
//要注意fns是引用型變量,實(shí)際是去除了this.eventList[key]下的方法。
if(fns[i] == fn){
fns.splice(i,1);
}
}
}
},
//trigger('loginSucc',參數(shù)1,參數(shù)2)
trigger:function(){
//出列第一個(gè)數(shù)據(jù):'loginSucc'
var key = Array.prototype.shift.call(arguments);
var fns = this.eventList[key];//拿到一組函數(shù)
if(!fns || fns.length === 0){
//沒(méi)有要執(zhí)行的函數(shù),就返回
return false;
}
for(var i=0;i<fns.length;i++){
//arguments已經(jīng)出列了一個(gè)數(shù)據(jù),目前全是參數(shù)列表了
fns[i].apply(this,arguments);
}
}
};
var installEvent = function(obj){
for(var i in event){
obj[i] = event[i];
}
}
var login = {};
installEvent(login);
//顯示頭像
function showAvatar(){
console.log('顯示用戶頭像');
}
//顯示消息列表
function showMessage(){
console.log('顯示消息列表');
}
//訂閱
login.listen('loginSuccess',showAvatar);
login.listen('loginSuccess',showMessage);
//發(fā)布
login.trigger('loginSuccess');
//取消訂閱
login.remove('loginSuccess',showAvatar);
//再次發(fā)布
login.trigger('loginSuccess');