[디자인 모델 시리즈] 의 [발표 - 구독 모드]

선언: 코드 수준 을 향상 시 키 려 면 디자인 모델 을 돌 릴 수 없다.전에 도 알 고 있 었 지만 깊이 공부 하지 못 했다.최근 에 디자인 모델 을 체계적으로 학습 하고 디자인, 디 결합 능력 을 향상 시 키 며 좋 은 책 인 을 발 견 했 기 때문에 읽 으 면서 쓰 고 자주 사용 하 는 디자인 모델 을 학습 하고 여기에 기록 했다.
게시 - 구독 모드
  • 정의 와 소개
  • 게시 - 구독 모드 의 예
  • 먼저 게시 하고 구독 해 야 합 니까?
  • 푸 시 모델 과 당 김 모델
  • 소결
  • 정의 와 소개
    게시 - 구독 모드 는 관찰자 모드 라 고도 부 릅 니 다. 대상 간 의 다 중 의존 관 계 를 정의 합 니 다. 대상 의 상태 가 바 뀌 면 모든 의존 대상 이 통 지 됩 니 다.자 바스 크 립 트 개발 에서 저 희 는 전통 적 인 게시 - 구독 모드 를 대체 하기 위해 이벤트 모델 을 사용 합 니 다.
    실제로 자주 사용 되 는 DOM 이 벤트 는 게시 - 구독 모드 입 니 다.
    document.body.addEventListener('click', function() {
    	alert(2);
    }, false)
    
    document.body.click();  //       
    

    우 리 는 사용자 가 클릭 document.body 하 는 동작 을 감청 하지만 사용자 가 언제 클릭 할 지 예측 할 수 없 기 때문에 우 리 는 document.bodyclick 사건 을 구독 합 니 다.클릭 이 발생 하면 구독 자 에 게 이 메 시 지 를 발표 합 니 다.
    게시 - 구독 모드 의 예
    이런 장면 을 가정 하면 많은 손님 들 이 분 양 부 에서 집 을 사 는 것 에 대해 문의 하지만 아직 개장 하지 않 았 기 때문에 손님 들 은 자신의 연락 처 를 분 양 부 에 남 겨 두 고 분 양 부 는 남 겨 진 연락처 에 따라 문의 한 고객 에 게 알려 준다.
    이것 이 바로 전형 적 인 게시 - 구독 모드 의 장면 이다.
    //     -    
    let Event = (function() {
    	//    Map, key        ,value        。
    	let clientList = {}, 
    	listen,
    	trigger,
    	remove;
    
    	//      ,         key        fn
    	listen = function(key, fn) {
    		if(!clientList[key]) {
    			clientList[key] = [];
    		}
    		clientList[key].push(fn);
    	};
    
    	//     ,               key,            
    	trigger = function() {
    		//        key
    		let key = Array.prototype.shift.call(arguments),
    		//         
    		fns = clientList[key];
    		if(!fns || fns.length === 0) {
    			return false
    		}
    		//     
    		for(let i=0; i<fns.length; i++) {
    			//           
    			fn.apply(this, arguments);
    		}
    	};
    
    	//     ,       key       
    	remove = function(key, fn) {
    		//   key       ,  
    		let fns = clientList[key];
    		if(!fns){
    			return false;
    		}
    		//           ,     key      
    		if(!fn) {
    			fns && (fns.length = 0);
    		} else {
    		//    ,         ,      
    			for(let i=fns.length-1; i>=0; i--) {
    				if(fns[i] === fn) {
    					fns.splice(i, 1);
    				}
    			}
    		}
    	}
    
    	return {
    		listen,
    		trigger,
    		remoce,
    	}
    })();
    
    //   88    
    Event.listen('squareMeter88', function() {
    	console.log(`price: ${price}`);
    })
    
    //        
    Event.trigger('squareMeter88', 20000)

    이런 장점 은:
  • 서로 다른 고객 은 수요 에 따라 구독 할 수 있 고 원 하 는 다양한 평형 을 예약 할 수 있 으 며 개장 할 때 알려 준다.구독 하지 않 은 평형 에 대해 서도 스 팸 메 시 지 를 받 지 않 는 다.
  • 새로운 고객 이 구독 해 야 할 때 이전의 코드 를 전혀 수정 하지 않 고 자신 이 listen 방법 으로 자신 을 구독 에 가입 하면 된다.

  • 먼저 게시 하고 구독 해 야 합 니까?
    위의 예 에서 모두 먼저 구독 하고 발표 할 때 알려 줍 니 다.그러나 반대로 구독 자가 없 을 때 메 시 지 를 올 렸 다 면 이 메 시 지 는 사 라 졌 다.
    우 리 는 QQ 위 챗 오프라인 메시지 처럼 구독 시 이전에 발표 한 소식 을 받 을 수 있 기 를 바 랍 니 다.이 를 만족 시 키 기 위해 서 는 오프라인 사건 을 저장 하 는 스 택 을 만들어 야 한다. 발표 할 때 구독 자가 없 으 면 먼저 그 를 저장 해 야 한다.마침내 대상 이 이 사건 을 구독 할 때, 우 리 는 다시 스 택 을 옮 겨 다 니 며, 다시 한 번 발표 하고, 발표 한 후에 스 택 에서 그것 을 삭제 합 니 다.
    코드:
    //               -    
    let Event = (function() {
    	//    Map, key        ,value        。
    	let clientList = {}, 
    	waitPublish = [], //             
    	listen,
    	trigger,
    	remove;
    
    	//      ,         key        fn
    	listen = function(key, fn) {
    		if(!clientList[key]) {
    			clientList[key] = [];
    		}
    		clientList[key].push(fn);
    		//   key        ,       ,       
    		if(clientList[key].length === 1) {
    			for(let i=0; i<waitPublish.length; i++) {
    				//     
    				fn.apply(this);
    				//      
    				waitPublish.splice(i, 1);
    			}
    		}
    	};
    
    	//     ,               key,            
    	trigger = function() {
    		//        key
    		let key = Array.prototype.shift.call(arguments),
    		//         
    		fns = clientList[key];
    		//       
    		if(!fns || fns.length === 0) {
    			//           
    			let waitFn = function() {
    				//     
    				trigger(key, ...arguments);
    			}
    			waitPublish.push(waitFn);
    			return false
    		}
    		//     
    		for(let i=0; i<fns.length; i++) {
    			//           
    			fn.apply(this, arguments);
    		}
    	};
    
    	//     ,       key       
    	remove = function(key, fn) {
    		//   key       ,  
    		let fns = clientList[key];
    		if(!fns){
    			return false;
    		}
    		//           ,     key      
    		if(!fn) {
    			fns && (fns.length = 0);
    		} else {
    		//    ,         ,      
    			for(let i=fns.length-1; i>=0; i--) {
    				if(fns[i] === fn) {
    					fns.splice(i, 1);
    				}
    			}
    		}
    	}
    
    	return {
    		listen,
    		trigger,
    		remoce,
    	}
    })();
    
    

    푸 시 모델 과 당 김 모델
    푸 시 모델: 이벤트 가 발생 할 때 게시 자 는 모든 데이터 와 상태 변 화 를 구독 자 에 게 한꺼번에 전달 합 니 다.
    라 모델: 게시 자 는 구독 자 에 게 만 사건 이 발생 했다 고 알 리 고 구독 자 는 공개 적 인 핑계 에 따라 자신 이 필요 로 하 는 데 이 터 를 자발적으로 끌 어 옵 니 다.
    모델 을 끌 어 당 기 는 것 은 필요 에 따라 얻 을 수 있 지만 게시 자 를 변화 시 킬 수 있 는 문 호 를 크게 열 고 코드 의 복잡 도 를 높 일 수 있다 는 것 이 장점 이다.JavaScript 의 arguments 는 매개 변수 목록 을 편리 하 게 표시 할 수 있 기 때문에 우 리 는 일반적으로 푸 시 모델 을 선택 하고 apply 방법 으로 모든 매개 변 수 를 구독 자 에 게 푸 시 합 니 다.
    작은 매듭
    자바 스 크 립 트 의 게시 구독 모드 는 다른 언어 와 다 릅 니 다. 자바 에 서 는 구독 자 자 자 체 를 게시 자 에 게 전달 하 는 경우 가 많 습 니 다. 자바 스 크 립 트 에 서 는 리 셋 함수 형식 으로 대체 하여 더욱 우아 하고 간단 합 니 다.
    게시 - 구독 모드 의 장점:
  • 시간 상의 디 결합, 구독 후 상관 하지 않 아 도 됩 니 다. 자 연 스 럽 게 알려 드 립 니 다
  • 대상 간 의 디 결합 은 광범 위 하 게 응용 된다.

  • 단점:
  • 구독 자 를 만 드 는 것 자체 가 메모 리 를 소모 해 야 합 니 다. 메 시 지 를 구독 한 후에 발표 되 지 않 았 을 수도 있 지만 메모리 에 항상 존재 합 니 다.
  • 대상 간 의 관 계 를 약화 시 켰 지만 과도 하 게 사용 하면 프로그램 추적 유지 가 어 려 울 수 있다.
  • 좋은 웹페이지 즐겨찾기