検索
ホームページウェブフロントエンドjsチュートリアルJavaScript デザイン パターンのオブザーバー パターンの詳細な紹介

JavaScript は、マウス応答、イベント コールバック、ネットワーク リクエストなどのイベント駆動型環境でアクティブになります。オブザーバー モードは、パブリッシャー/サブスクライバー モード とも呼ばれます。オブジェクト間の関係、その動作と状態を扱い、人々とタスクの関係を管理します。 观察者模式又称发布者-订阅者(publisher-subscriber)模式,是处理对象及其行为和状态之间的关系,管理人与任务之间的关系。

1. 最常见的观察者模式

1.1 事件监听器
document.body.addEventListener('click', function () {
    console.log('you clicked me, poor guy!')
});

这是最简单最普通的一种观察者模式,除此click 以外还有loadblurdragfocusmouseover、等。事件监听器(listener)有别于事件处理器(handler),在事件监听器中,一个事件可以关联多个监听器,每个监听器独立处理监听到的消息;事件处理器是执行处理事件发生后的关联函数,一种事件是能有一个处理函数:

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);

在这个事件监听器的例子中,listener1listener2 都是dom元素的监听器,当dom被点击时,都会执行各自的函数;

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 观察者的构建

首先,需要一个发布者。先定义一个构造函数,为其定义一个数组,用以保存订阅者信息:

function Publisher(){
    this.subscribes = [];
}

发布者具有发布消息的功能,定义一个deliver的原型函数:

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;
}

直接在Function的prototype添加subscribe方法,这样所有函数都可以调用该方法。这样就构建完毕了,使用方法参看1.2动画的用例。
比较直观的解释(以onStart为例):box对象执行look方法时,执行onStart.deliver(),将onStart事件发布出去,广播通知'animation started!',这个时候,一直在监听onStartopenBox监听到该事件发布的信息,打印出来。

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中有events模块来实现观察者模式,可参考Nodejs API-Events 谈观察者模式,大多数的模块都集成了events模块,所以可以直接使用emit发射事件和on监听事件,或者像下面这样先定义一下;

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 总结

观察者模式建立了推送收听

1. 最も一般的なオブザーバー パターン

1.1 イベント リスナー
rrreeeこれは、click を除く最も単純で最も一般的なオブザーバー パターンです。 、<code>loadblurdragfocusmouseover、wait もあります。 。イベント リスナー (リスナー) はイベント ハンドラー (ハンドラー) とは異なります。イベント リスナーでは、イベントを複数のリスナーに関連付けることができ、各リスナーは監視対象のメッセージを個別に処理します。イベント ハンドラーはイベントの実行と処理を担当します。関連付けられた関数の後に、イベントにハンドラー関数を含めることができます:

rrreee

このイベント リスナーの例では、listener1listener2 は両方とも DOM 要素のリスナーです。 dom がクリックされると、それぞれの関数が実行されます

rrreee このイベント ハンドラーの例では、handler1 は実行されず、handler2 のみが実行されます。代入操作です。

1.2 アニメーション

オブザーバー モードはアニメーションで広く使用されており、アニメーションの開始、完了、一時停止などには、オブザーバーがオブジェクトの動作とステータスを判断する必要があります。

rrreee

1.3 オブザーバーの構築

まず、パブリッシャーが必要です。まず、サブスクライバー情報を保存するためのコンストラクターと配列を定義します: rrreee パブリッシャーにはメッセージを公開する機能があり、deliver のプロトタイプ関数を定義します:

rrreee 次に、サブスクリプション メソッドを構築します: rrreee

サブスクライブを直接追加しますメソッドを関数プロトタイプに追加して、すべての関数がこのメソッドを呼び出せるようにします。以上で構築が完了します。使用方法は1.2 アニメーションの使用例を参照してください。
より直感的な説明 (onStart を例にします): box オブジェクトが look を実行するとき> メソッドで、onStart.deliver() を実行し、onStart イベントを発行して、通知 'animation starting!' をブロードキャストします。それはリッスンしていますonStart の openBox は、イベントによってリリースされた情報をリッスンし、それを出力します。 🎜

1.4 オブザーバーを構築する別の方法

🎜 このメソッドは、nodejs のイベント処理メカニズムを模倣しており、コードは比較的簡潔です: 🎜rrreee

1.5 nodejs でのオブザーバー パターンの実装計画 h4 >🎜nodejs にはオブザーバー モードを実装するためのイベント モジュールがあります。オブザーバー モードについては、Nodejs API-Events を参照してください。ほとんどのモジュールはイベント モジュールを統合しているため、直接 Emit を使用してイベントを起動し、リッスンすることができます。イベントの場合は、次のように定義します。最初に次のように定義します。🎜rrreee🎜共通メソッド: 🎜
  • 🎜hasConfortListener: 発行されたイベントにリスナーがあるかどうかを判断するために使用されます🎜 li>
  • 🎜removeListener : リスナーを削除します🎜
  • 🎜listenerCount : このイベントのすべてのリスナーの合計数🎜
  • 🎜removeAllListeners : イベントのすべて (または 1 つ) のリスナーを削除しますイベント🎜

1.6 概要

🎜 オブザーバー モードは、pushlisten のロジックを確立し、アプリケーションに適しています。人間の行動を別の機会に監視したいと考えています。たとえば、ユーザーがナビゲーション バーのタブをクリックすると、さらに多くのオプションを含むサブメニューが開きます。通常、ユーザーは、どの要素がわかっているかを知っていれば、クリック イベントを直接聞くことを選択します。クリック イベントと同じです。イベントは直接結び付けられます。より良いアプローチは、監視可能な onTabChange オブジェクトを作成し、複数のオブザーバー実装を関連付ける方法です。 🎜🎜関連記事: 🎜🎜🎜古典的なJavaScriptデザインパターン、ストラテジパターンの詳細説明🎜🎜🎜🎜JavaScriptデザインパターン、古典的なシンプルファクトリーパターンのコード例🎜🎜🎜🎜古典的なJavaScriptデザインパターン、シングルトンの詳細説明パターン🎜🎜

以上がJavaScript デザイン パターンのオブザーバー パターンの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)