發(fā)布訂閱模式
在“發(fā)布者-訂閱者”模式中渴逻,稱為發(fā)布者的消息發(fā)送者不會將消息編程為直接發(fā)送給稱為訂閱者的特定接受者,這意味著發(fā)布者和訂閱者不知道彼此的存在音诫。存在第三個組件裸卫,稱為消息代理或調(diào)度中心,他由發(fā)布者和訂閱者都知道纽竣,他過濾所有傳入的消息并相應地分發(fā)他們墓贿。
//先有訂閱茧泪,再有發(fā)布
class PubSub{
constructor(){
this.sub = {}; //訂閱者名單
}
subscribe(type,handler){ //訂閱
/*
@type : 訂閱者標識
@handler : 訂閱者具體訂閱內(nèi)容
*/
if(!this.sub[type]){ // 如果該對象不存在訂閱名單初始化一個數(shù)組
this.sub[type] = [];
}
this.sub[type].push(handler); //如果該對象存在于訂閱者名單中,就push進數(shù)組
}
publish(type,params){
/*
@type : 訂閱者標識
@params : 發(fā)布時的額外參數(shù)
*/
if(!(type in this.sub)){
console.log(type+'該對象沒有訂閱')
return;
}
this.sub[type].forEach((handler)=>{ //發(fā)布 遍歷該對象下的所有訂閱的事件 進行執(zhí)行
handler(params)
})
}
removeSub(type,handler){
if(!(type in this.sub)){
console.log( type+'該對象沒有訂閱')
return;
}
if(!handler){
delete this.sub[type]
}else{
let idx = this.sub[type].findIndex((item)=>{
return item == handler
})
if(idx<0){
console.log(type+'沒有訂閱過此事件');
return;
}
this.sub[type].splice(idx,1);
if(this.sub[type].length<=0){
delete this.sub[type]
}
}
}
}
//Example:
function xiaoming(params){
console.log('我是小明訂閱的事件'+params)
}
function xiaohong1(params){
console.log('我是小紅訂閱的事件1'+params)
}
function xiaohong2(params){
console.log('我是小紅訂閱的事件2'+params)
}
let pubsub = new PubSub();
pubsub.subscribe('小明',xiaoming);
pubsub.subscribe('小紅',xiaohong1);
pubsub.subscribe('小紅',xiaohong2);
pubsub.removeSub('小紅',xiaohong2)
pubsub.publish('小明','發(fā)布了');
pubsub.publish('小紅','發(fā)布了');
觀察者模式
觀察者模式指的是一個對象(Subject)維持一系列依賴于他的對象(Observer),當有關狀態(tài)發(fā)生變更時Subject對象通知一系列Observer對象進行更新聋袋。
class Subject{
constructor(){
this.obList = []; //observer 集合
this.state = 1; //默認狀態(tài)
}
getState(){ // 讀取狀態(tài)監(jiān)聽
console.log('我被讀取了')
return this.state;
}
setState(value){ //重寫狀態(tài)監(jiān)聽
console.log('我被重寫了')
this.state = value;
this.notifyAllOber(); //重寫時通知所有的觀察者
}
attach(ob){ // 添加觀察者
this.obList.push(ob);
}
notifyAllOber(){
this.obList.forEach((ob)=>{ //核心 通知所有觀察者進行更新
ob.update();
})
}
};
class Observer{
constructor(name,subject){
this.name = name;
this.subject = subject;
this.subject.attach(this); // 添加觀察者
}
update(){
console.log(this.name,'我觀察到了變化')
}
}
let subject = new Subject();
let observer = new Observer('我是張三',subject);
subject.setState(2)
單例模式
單例模式是指保證一個類僅有一個實例队伟,并提供一個訪問它的全局節(jié)點。實現(xiàn)方式是先判斷實例是否存在幽勒,如果存在則直接返回嗜侮,如果不存在就創(chuàng)建之后再返回,這就確保了一個類只有一個實例對象啥容。
比如最簡單的單例模式:
var instance = null;
function getNum(num){
if(!instance){
return instance = num;
}
return instance;
}
var a = getNum(10);
var b = getNum(20)
console.log(a);//10
console.log(b);//10
這實際上就是一個單例模式锈颗,但是它的所有變量都暴露在全局不是很好,我們使用一下立即執(zhí)行函數(shù)加閉包這么寫一下咪惠。
class Num{
constructor(num){
this.num = num;
}
getNum(){
return this.num;
}
}
let createInstance = (function(){
var instance = null;
return function(num){
if(!instance){
instance = new Num(num)
}
return instance;
}
})();
var num1 = createInstance(10);
var num2 = createInstance(20);
console.log(num1===num2) //true
策略模式
策略模式指的是定義一系列的算法击吱,把他們一個個封裝起來,并且使他們可以相互替換遥昧。
一個基于策略模式的程序至少有兩部分組成覆醇,一部分是策略類
(可變),它封裝了具體算法炭臭,并負責整個具體計算過程永脓,另一部分是環(huán)境類
(不變),環(huán)境類
接收客戶的請求鞋仍,隨后將請求委托給某一個策略類常摧。也就是說在環(huán)境類中維持對某個策略的引用。
比如財務部門算年終獎威创,不同的身份有不同的獎金額度落午。
舉例:CEO : 10個月獎金,CTO:5個月獎金那婉,CFO:4個月獎金,COO:2個月獎金党瓮。
如果使用正常的邏輯去做那就是使用if條件判斷職位類型详炬。使用策略模式可以參考一下代碼
//策略類
var strategies = {
"CEO":function(bonus){ //首席執(zhí)行官
return bonus*10
},
"CTO":function(bonus){ //首席技術官
return bonus*5
},
"CFO":function(bonus){ //首席財務官
return bonus*4
},
"COO":function(bonus){ //首席運營官
return bonus*2
}
}
var calculateBonus = function(position,bonus){
return strategies[position](bonus);
}
//環(huán)境類
var ceobonus = calculateBonus('CEO',50);
var ctobonus = calculateBonus('CTO',30);
console.log(ceobonus,ctobonus);//500 150
未完待續(xù)。寞奸。呛谜。