>  기사  >  웹 프론트엔드  >  JavaScript 디자인 패턴 중 관찰자 패턴에 대한 자세한 소개

JavaScript 디자인 패턴 중 관찰자 패턴에 대한 자세한 소개

高洛峰
高洛峰원래의
2017-03-20 11:03:431256검색

Javascript는 마우스 응답, 이벤트 콜백, 네트워크 요청 등과 같은 이벤트 기반 환경에서 활성화됩니다. 观察者라고도 알려진 发布者-订阅者(publisher-subscriber)模式 모드는 개체 간의 관계, 해당 동작 및 상태를 처리합니다. 사람과 업무의 관계를 관리합니다.

1. 가장 일반적인 관찰자 패턴

1.1 이벤트 리스너
document.body.addEventListener('click', function () {
    console.log('you clicked me, poor guy!')
});

가장 간단하고 일반적인 관찰자 패턴입니다. click도 있습니다. load, blur, drag, focus 등 이벤트 리스너(리스너)는 이벤트 핸들러(핸들러)와 다릅니다. 이벤트 리스너에서는 이벤트가 여러 리스너와 연결될 수 있으며 각 리스너는 모니터링되는 메시지를 독립적으로 처리합니다. 이벤트 핸들러는 이벤트 실행 및 처리를 담당합니다. . 관련 함수 뒤에 이벤트는 핸들러 함수를 가질 수 있습니다: mouseover

var dom = $('.dom');
var listener1 = function(e){
    //do one thing
}
var listener2 = function(e){
    //do another thing
}
addEvent(dom,'click',listener1);
addEvent(dom,'click',listener2);
이 이벤트 리스너 예에서

listener1는 모두 dom 요소에 대한 리스너입니다. 해당 기능이 실행됩니다. listener2

var dom = document.getElementById('dom');
var handler1 = function(e){
    //do one thing
}
var handler2 = function(e){
    //do another thing
}
dom.onclick = handler1;
dom.onclick = handler2;
이 이벤트 핸들러의 예에서

는 실행되지 않고 할당 작업인 handler1만 실행됩니다. handler2

1.2 애니메이션

관찰자 모드는 애니메이션에서 널리 사용됩니다. 애니메이션의 시작, 완료, 일시정지 등을 수행하려면 관찰자가 개체의 동작과 상태를 결정해야 합니다.

//定义动画
var Animation = function(){
    this.onStart = new Publisher;  //关于Publisher的设计将在1.3节介绍
    this.onComplete = new Publisher;
    this.onTween = new Publisher;
}
//定义一个原型方法
Animation.prototype.look = function(){
    this.onStart.deliver('animation started!');
    this.onTween.deliver('animation is going on!');
    this.onComplete.deliver('animation completed!');  
};

//实例一个box对象
var box = new Animation();

//定义三个函数作为subscribers
var openBox = function(msg){
    console.log(msg)
}
var checkBox = function(msg){
    console.log(msg)
}
var closeBox = function(msg){
    console.log(msg)
}

//订阅事件
openBox.subscribe(box.onStart);
checkBox.subscribe(box.onTween);
closeBox.subscribe(box.onComplete);

//调用方法
box.look()

//animation started!
//animation is going on!
//animation completed!
1.3 Observer 구축

먼저 퍼블리셔가 필요합니다. 먼저 구독자 정보를 저장하기 위한 생성자와 배열을 정의합니다:

function Publisher(){
    this.subscribes = [];
}
게시자는 메시지를 게시하는 기능을 가지고 있으며 전달의 프로토타입 기능을 정의합니다:

Publisher.prototype.deliver = function(data){
    this.subscribes.forEach(function(fn){
        fn(data);
    });
    return this;
}
다음 구독 메소드를 구성합니다. :

Function.prototype.subscribe = function(publisher){
    var that = this;
    var alreadyExists = publisher.subscribes.some(function(el){
        return el === that;
    });
    if(!alreadyExists){
        publisher.subscribes.push(this);
    }
    return this;
}
모든 함수가 이 메서드를 호출할 수 있도록 구독 메서드를 함수 프로토타입에 직접 추가하세요. 이렇게 해서 구축이 완료되었습니다. 사용방법은 1.2 Animation의 Use Case를 참고하시기 바랍니다.


보다 직관적인 설명(을 예로 들어): onStart 객체가 box 메서드를 실행할 때 look을 실행하고 onStart.deliver() 이벤트를 게시하고 브로드캐스트합니다. 알림onStart, 이때 'animation started!'을 듣고 있던 onStart이(가) 이벤트에서 공개된 정보를 듣고 인쇄합니다. openBox

1.4 관찰자를 구축하는 또 다른 방법

이 방법은 nodejs의 이벤트 처리 메커니즘을 모방하고 코드가 비교적 간결합니다.

    var scope = (function() {
    //消息列表
    var events = {};
    return {
        //订阅消息
        on:function(name,hander){
            var index = 0;  //记录消息时间的索引
            if(events[name]){  
                //消息名已存在,将处理函数放到该消息的事件队列中
                index = events[name].push(hander) - 1; 
            }else{
                events[name] = [hander];
            }
            //返回当前消息处理事件的移除函数
            return function(){
                events[name].splice(index,1);
            }
        },
        //关闭消息
        off:function(name){
            if(!events[name]) return;
            //消息存在,删除消息
            delete events[name];
        },
        //消息发布
        emit:function(name,msg){
            //消息不存在,不处理
            if(!events[name]) return;
            //消息存在,将该事件处理队列中每一个函数都执行一次
            events[name].forEach(function(v,i){
                v(msg);
            });
        }
    }
})();

var sayHello = scope.on('greeting',function(msg){
    console.log('订阅消息:' + msg);
});

var greeting = function(msg){
    console.log('发布消息:' + msg);
    scope.emit('greeting', msg);
}

greeting('hello Panfen!')
1.5 nodejs의 관찰자 모드 구현 계획

nodejs에는 관찰자 모드를 구현하는 이벤트 모듈이 있습니다. Nodejs API-이벤트를 참조하여 관찰자 모드에 대해 설명할 수 있습니다. 대부분의 모듈은 이벤트 모듈을 통합하므로 직접 생성하여 이벤트를 시작할 수 있습니다. 이벤트를 수신하거나 아래와 같이 먼저 정의하세요.

var EventEmitter = require('events').EventEmitter;
var life = new EventEmitter();
life.setMaxListeners(11);       //设置最大监听数,默认10

//发布和订阅sendName
life.on('sendName',function(name){
    console.log('say hello to '+name);
});
life.emit('sendName','jeff');

//发布和订阅sendName2
function sayBeautiful(name){
    console.log(name + ' is beautiful');
}
life.on('sendName2',sayBeautiful);
life.emit('sendName2','jeff');
일반적인 메서드:

  • hasConfortListener: 생성된 이벤트에 리스너가 있는지 확인하는 데 사용됩니다

  • removeListener: 리스너 제거

  • listenerCount: 이 이벤트에 대한 모든 리스너의 총 수

  • removeAllListeners : 모두(또는 하나) 이벤트 리스너 제거

1.6 요약

관찰자 패턴은

推送의 논리를 설정하며 원하는 사람들에게 적합합니다. 애플리케이션의 동작은 애플리케이션의 동작과 별개입니다. 예를 들어, 사용자가 탐색 모음의 탭을 클릭하면 더 많은 옵션이 포함된 하위 메뉴가 열립니다. 일반적으로 사용자는 어떤 요소를 알고 있으면 클릭 이벤트를 직접 수신하도록 선택합니다. 클릭 이벤트와 동일합니다. 이벤트는 서로 직접 연결됩니다. 더 나은 접근 방식은 관찰 가능한 onTabChange 객체를 만들고 여러 관찰자 구현을 연결하는 것입니다. 收听

관련 기사:

클래식 JavaScript 디자인 패턴, 전략 패턴에 대한 자세한 설명

클래식 JavaScript 디자인 패턴, 단순 팩토리 패턴 코드 예시

고전적인 JavaScript 디자인 패턴 싱글턴 패턴에 대한 자세한 설명

위 내용은 JavaScript 디자인 패턴 중 관찰자 패턴에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.