소개하다
옵저버 모드를 게시/구독이라고도합니다. 그것은 일대일 관계를 정의하여 여러 관찰자 객체가 동시에 주제 객체를들을 수 있도록합니다. 이 주제의 상태가 변경되면 모든 관찰자 객체가 알림을 받으므로 자동으로 스스로 업데이트 할 수 있습니다.
옵저버 모드 사용의 이점 :
1. 간단한 방송 통신을 지원하고 구독 된 모든 객체에 자동으로 알립니다.
2. 페이지가로드 된 후 대상 객체는 관찰자와 쉽게 동적 상관 관계를 가질 수있어 유연성이 증가합니다.
3. 대상 객체와 관찰자 사이의 추상 커플 링 관계를 별도로 확장하고 재사용 할 수 있습니다.
텍스트 (버전 1)
JS에서 관찰자 패턴의 구현은 콜백을 통해 달성됩니다. 먼저 구독, 구독 및 게시의 3 가지 방법이 포함 된 PubSub 객체를 정의하겠습니다.
코드 사본은 다음과 같습니다.
var pubsub = {};
(기능 (Q) {
var topics = {}, // 콜백 함수에 의해 저장된 배열
subuid = -1;
// 방법을 게시합니다
q.publish = function (topic, args) {
if (! 주제 [주제]) {
거짓을 반환합니다.
}
settimeout (function () {
var 가입자 = 주제 [주제],
len = 가입자? 가입자. 길이 : 0;
while (len--) {
가입자 [len] .func (주제, args);
}
}, 0);
진실을 반환하십시오.
};
// 구독 방법
Q.SubScribe = function (주제, func) {
if (! 주제 [주제]) {
주제 [주제] = [];
}
var token = (++ subUid) .toString ();
주제 [주제] .push ({
토큰 : 토큰,
func : func
});
복귀 토큰;
};
// 소독 방법
q.unsubscribe = function (토큰) {
(주제의 var m) {
if (주제 [m]) {
for (var i = 0, j = 주제 [m] .length; i <j; i ++) {
if (주제 [m] [i] .token === 토큰) {
주제 [m] .splice (i, 1);
복귀 토큰;
}
}
}
}
거짓을 반환합니다.
};
} (pubsub));
사용 방법은 다음과 같습니다.
코드 사본은 다음과 같습니다.
// 와서 하나를 구독하십시오
pubsub.subscribe ( 'example1', function (주제, 데이터) {
Console.log (주제 + ":" + data);
});
// 릴리스 통지
pubsub.publish ( 'example1', 'hello world!');
pubsub.publish ( 'example1', [ 'test', 'a', 'b', 'c']);
pubsub.publish ( 'example1', [{ 'color': 'blue'}, { 'text': 'hello'}]);
어때? 사용하는 것이별로 좋지 않습니까? 그러나이 방법에는 문제가 있습니다. 즉, 구독을 취소 할 방법이 없습니다. 구독 취소하려면 구독 취소 이름을 지정해야하므로 다른 버전으로 가야합니다.
코드 사본은 다음과 같습니다.
// 구독을 변수에 할당하여 구독 취소
var testsubscription = pubsub.subscribe ( 'example1', function (주제, 데이터) {
Console.log (주제 + ":" + data);
});
// 릴리스 통지
pubsub.publish ( 'example1', 'hello world!');
pubsub.publish ( 'example1', [ 'test', 'a', 'b', 'c']);
pubsub.publish ( 'example1', [{ 'color': 'blue'}, { 'text': 'hello'}]);
// 수신 실시되지 않습니다
settimeout (function () {
pubsub.unsubscribe (testsubscription);
}, 0);
// 정보가 여전히 출력 될 수 있는지 확인하기 위해 다시 게시합니다.
pubsub.publish ( 'example1', 'hello 다시! (이것은 실패 할 것입니다)');
버전 2
또한 프로토 타입의 특성을 사용하여 관찰자 패턴을 구현할 수 있습니다. 코드는 다음과 같습니다.
코드 사본은 다음과 같습니다.
함수 옵저버 () {
this.fns = [];
}
Observer.prototype = {
구독 : 기능 (fn) {
this.fns.push (fn);
},
수신 취소 : 기능 (fn) {
this.fns = this.fns.filter (
함수 (el) {
if (el! == fn) {
el el;
}
}
);
},
업데이트 : 함수 (O, thisobj) {
var scope = thisobj || 창문;
this.fns.foreach (
함수 (el) {
el.call (스코프, o);
}
);
}
};
//시험
var o = 새로운 관찰자;
var f1 = function (data) {
Console.log ( 'Robbin :' + data + ', 빨리 작동합니다!');
};
var f2 = function (data) {
console.log ( 'randall :' + data + ', 추가 급여를받을 수있는 것을 찾으십시오!');
};
O.Subscribe (F1);
O.Subscribe (F2);
o.update ( "톰이 돌아 왔어요!")
// f1을 구독 취소합니다
o.unsubscribe (f1);
// 다시 확인하십시오
O.update ( "Tom이 돌아 왔어요!");
필터 또는 Foreach 함수를 찾을 수없는 경우 브라우저가 충분히 새롭지 않고 당분간 새로운 표준 기능을 지원하지 않기 때문일 수 있습니다. 다음과 같은 방식으로 직접 정의 할 수 있습니다.
코드 사본은 다음과 같습니다.
if (! array.prototype.foreach) {
Array.prototype.foreach = function (fn, thisobj) {
var scope = thisobj || 창문;
for (var i = 0, j = this.length; i <j; ++ i) {
fn.call (범위,이 [i], i, this);
}
};
}
if (! array.prototype.filter) {
Array.prototype.filter = function (fn, thisobj) {
var scope = thisobj || 창문;
var a = [];
for (var i = 0, j = this.length; i <j; ++ i) {
if (! fn.call (범위, this [i], i, this)) {
계속하다;
}
A.push (이 [i]);
}
반환 a;
};
}
버전 3
여러 객체가 관찰자 게시 구독 기능을 갖기를 원한다면 공통 함수를 정의한 다음 관찰자 기능이 필요한 객체에 함수의 기능을 적용 할 수 있습니다. 코드는 다음과 같습니다.
코드 사본은 다음과 같습니다.
// 범용 코드
var observer = {
//신청
AddSubscriber : function (콜백) {
this.subscribers [this.subscriber.length] = 콜백;
},
// 수신 실시되지 않습니다
제거 서브 스크립터 : 함수 (콜백) {
for (var i = 0; i <this.subscriber.length; i ++) {
if (this.subscribers [i] === 콜백) {
삭제 (this.subscribers [i]);
}
}
},
//풀어 주다
게시 : 기능 (What) {
for (var i = 0; i <this.subscriber.length; i ++) {
if (typeof this.subscribers [i] === 'function') {
this.subscribers [i] (what);
}
}
},
// Object O에 관찰자 기능이 있습니다
MATE : 기능 (O) {
for (var i in this) {
o [i] = 이것은 [i];
O.Subscribers = [];
}
}
};
그런 다음 2 개의 객체 블로거와 사용자를 구독하고 관찰자를 사용하여 메소드를 사용 하여이 두 객체에 관찰자 기능이 있도록 코드는 다음과 같습니다.
코드 사본은 다음과 같습니다.
var blogger = {
추천 : function (id) {
var msg = 'dudu 권장 게시물 :' + id;
this.publish (msg);
}
};
var user = {
투표 : 기능 (ID) {
var msg = '누군가 투표! id =' + id;
this.publish (msg);
}
};
Observer.make (Blogger);
Observer.make (사용자);
사용법은 비교적 간단합니다. 다른 콜백 함수를 구독하여 다른 관찰자 객체 (또는 여러 관찰자 객체를 동시에 등록 할 수 있음)를 등록 할 수 있습니다.
코드 사본은 다음과 같습니다.
var tom = {
읽기 : 기능 (What) {
Console.log ( 'Tom은 다음과 같은 메시지를 보았습니다.' + What)
}
};
var mm = {
쇼 : 기능 (What) {
Console.log ( 'MM은 다음 메시지를 보았습니다.' + What)
}
};
// 구독하다
blogger.addsubscriber (Tom.read);
blogger.addsubscriber (mm.show);
Blogger.recommend (123); // 전화로 전화하십시오
// 수신 실시되지 않습니다
Blogger.removesubscriber (mm.show);
Blogger.recommend (456); // 전화로 전화하십시오
// 다른 개체를 구독하십시오
user.addsubscriber (mm.show);
user.vote (789); // 전화로 전화하십시오
jQuery 버전
jQuery 버전 1.7에 추가 된 ON/OFF 기능에 따르면 jQuery 버전의 관찰자를 정의 할 수도 있습니다.
코드 사본은 다음과 같습니다.
(기능 ($) {
var o = $ ({});
$ .subscribe = function () {
O.on.apply (o, 인수);
};
$ .unsubscribe = function () {
O.Off.Apply (o, 인수);
};
$ .publish = function () {
o.trigger.apply (o, 인수);
};
} (jQuery));
호출 방법은 위의 세 가지 버전보다 간단합니다.
코드 사본은 다음과 같습니다.
// 콜백 함수
함수 핸들 (E, A, B, C) {
//`e`는 이벤트 객체이며주의가 필요하지 않습니다.
Console.log (A + B + C);
};
//신청
$ .subscribe ( "/some/topic", handle);
//풀어 주다
$ .publish ( "/some/topic", [ "a", "b", "c"]); // abc를 출력합니다
$ .unsubscribe ( "/some/topic", handle); // 구독 취소
//신청
$ .Subscribe ( "/some/topic", function (e, a, b, c) {
Console.log (A + B + C);
});
$ .publish ( "/some/topic", [ "a", "b", "c"]); // abc를 출력합니다
// 구독 취소 (구독 취소 콜백 함수가 아닌/일부/주제 이름을 사용합니다. 버전 1의 예와는 다릅니다.
$ .unsubscribe ( "/some/topic");
구독 및 구독 취소는 콜백 함수 이름이 아닌 문자열 이름을 사용한다는 것을 알 수 있습니다. 따라서 들어오는 익명 함수가 전달 되더라도 구독을 취소 할 수 있습니다.
요약
관찰자의 사용은 다음과 같습니다. 객체가 다른 객체를 동시에 변경하기 위해 변경하고 얼마나 많은 객체를 변경 해야하는지 알지 못하면 관찰자 모드 사용을 고려해야합니다.
전반적으로, 관찰자 패턴이하는 일은 분리하는 것입니다. 커플 링의 양쪽은 콘크리트보다는 추상화에 의존합니다. 이로 인해 서로의 변화가 다른 쪽의 변화에 영향을 미치지 않을 수 있습니다.