Publisher / Subscriber Design Pattern : A JavaScript Implementation

This website is no longer actively supported

Written by John DeVightJohn DeVight on 13 Jun 2011 17:34

Download the source code here.

Overview

The Publisher / Subscriber design pattern, also known as the Observer pattern, is a messaging pattern where subscribers express an interest in certain types of messages without knowledge of what objects may be publishing the messages. An implementation of the Publisher / Subscriber design pattern involves the use of a broker. The subscribers register with a broker for certain types of messages. Publishers send messages to brokers and the broker handles the distribution of the message to subscribers. Objects can be both publishers and subscribers.

The implementation of the Publisher / Subscriber design pattern is dependant on the json2.js file which can be found on the wiki page: JSON Extension Functions

observer.js

Here is the observer.js code:

/*******************************************************************************
 *
 * MessageBroker Class.
 *
 ******************************************************************************/

/// <summary>
/// Constructor for the MessageBroker class.  Create an instance of an ArrayList
/// as the container for all the subscribers.
/// </summary>
function MessageBroker() {
    this.subscribers = [];
}

/// <summary>
/// Notify all subscribers who are interested in an event.
/// </summary>
/// <param name="event" type="string">Name of the event to notify subscribers about.</param>
/// <param name="args" type="object">arguments to be passed to the subscribers.</param>
MessageBroker.prototype.Notify = function(event, args) {
    var count = this.subscribers.length;

    // Loop through all the subscribers...
    for (var i = 0; i < count; i++) {
        // If the subscriber is for this event....
        if (this.subscribers[i].Event == event) {
            // Call the function pointer and pass in the arguements.
            this.subscribers[i].Subscriber(args);
        }
    }
}

/// <summary>
/// Add a subscriber for an event.
/// </summary>
/// <param name="event" type="string">Name of the event that the subscriber is interested in.</param>
/// <param name="subsctiber" type="function pointer">Pointer to a function to be called if the event occurs.</param>
MessageBroker.prototype.AddSubscriber = function(event, subscriber) {
    this.subscribers.push( { Event: event, Subscriber: subscriber });
}

/// <summary>
/// Remove a subscriber from an event.
/// </summary>
/// <param name="event" type="string">Name of the event that the subscriber was interested in.</param>
/// <param name="subsctiber" type="function pointer">Pointer to a function that was to be called if the event occurred.</param>
MessageBroker.prototype.RemoveSubscriber = function(event, subscriber) {
    JSON.removeArrayElement(this.subscribers, 'Subscriber', subscriber);
}

/*******************************************************************************
 *
 * MessageBroker Class.
 *
 ******************************************************************************/

/// <summary>
/// Constructor for the MessageBroker class.  Create an instance of an ArrayList
/// as the container for all the subscribers.
/// </summary>
function MessageBroker() {
    this.subscribers = [];
}

/// <summary>
/// Notify all subscribers who are interested in an event.
/// </summary>
/// <param name="event" type="string">Name of the event to notify subscribers about.</param>
/// <param name="args" type="object">arguments to be passed to the subscribers.</param>
MessageBroker.prototype.Notify = function(event, args) {
    var count = this.subscribers.length;

    // Loop through all the subscribers...
    for (var i = 0; i < count; i++) {
        // If the subscriber is for this event....
        if (this.subscribers[i].Event == event) {
            // Call the function pointer and pass in the arguements.
            this.subscribers[i].Subscriber(args);
        }
    }
}

/// <summary>
/// Add a subscriber for an event.
/// </summary>
/// <param name="event" type="string">Name of the event that the subscriber is interested in.</param>
/// <param name="subsctiber" type="function pointer">Pointer to a function to be called if the event occurs.</param>
MessageBroker.prototype.AddSubscriber = function(event, subscriber) {
    this.subscribers.push( { Event: event, Subscriber: subscriber });
}

/// <summary>
/// Remove a subscriber from an event.
/// </summary>
/// <param name="event" type="string">Name of the event that the subscriber was interested in.</param>
/// <param name="subsctiber" type="function pointer">Pointer to a function that was to be called if the event occurred.</param>
MessageBroker.prototype.RemoveSubscriber = function(event, subscriber) {
    JSON.removeArrayElement(this.subscribers, 'Subscriber', subscriber);
}

var _messageBroker = new MessageBroker();

Implemention of the MessageBroker

Publisher

The publisher "publishes" messages to the broker with the _messageBroker.Notify function.

Here is an example:

var Layout = {};

Layout.MainSplitter_Resize = function() {
    var height = $(window).height();
    var splitter = $('#MainSplitter');
    splitter.height(height - 25);
    splitter.resize();
}

Layout.InnerSplitter_OnResize = function(e) {
    _messageBroker.Notify("InnerSplitterResizeEvent");
}

Subscriber

A subscriber "subscribes" with the broker to receive a type of message (or event) with the _messageBroker.AddSubscribe function.

Here is an example:

var Index = {};

Index.Init = function() {
    Index.Resize();
    $(window).resize(Index.Resize);

    _messageBroker.AddSubscriber("InnerSplitterResizeEvent", function() { Index.Resize(); });
}

Index.Resize = function() {
    var contentPane =  $($('#InnerSplitter').children()[2]);
    var height = contentPane.height();
    var width = contentPane.width();

    // Resize the tab control to fit in the contract splitter.
    var tabStripCtrl = $('#IndexTabStrip');
    tabStripCtrl.height(height - 2);
    tabStripCtrl.width(width - 2);

    $('#tabOneContents').height(tabStripCtrl.height() - 50);
    $('#tabTwoContents').height(tabStripCtrl.height() - 50);
}

References

Comments

Add a New Comment

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License