The Observer Pattern

Intent

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Also Known As

Dependents, Publish-Subscribe

Motivation

A scenario that illustrates a design problem and how the class and object structures in the pattern solve the problem.
The scenario will help you understand the more abstract description of the pattern that follows.

Applicability

  • What are the situations in which the design pattern can be applied?
  • What are examples of poor designs that the pattern can address?
  • How can you recognise these situations?

Structure

A graphical representation of the classes in the pattern using a notation based on the Unified Modeling Language (UML).
We also use interaction diagrams to illustrate sequences of requests and collaborations between objects.

You can use ArgoUML as a free software to create UML class diagrams (http://argouml.tigris.org/\ or give a look at this list https://en.wikipedia.org/wiki/List_of_Unified_Modeling_Language_tools

Participants

The classes and/or objects participating in the design pattern and their responsibilities.

Collaborations

How the participants collaborate to carry out their responsibilities.

Consequences (aka Pros and Cons)

  • How does the pattern support its objectives?
  • What are the trade-offs and results of using the pattern?
  • What aspect of system structure does it let you vary independently?

Implementation

  • What pitfalls, hints, or techniques should you be aware of when implementing the pattern?
  • Are there language-specific issues?

Sample Code

The repo is here: https://github.com/andrixb/js\_design\_patterns/tree/BEHAVIORAL-DP/Observer

(function () {
    var subjectEl = document.querySelector('.subject__container');
    var observers = document.querySelectorAll('.observer__container');
    var totObservers = [];

    var Observer = function (element) {
        var _$ = {
            element: element
        };

        var _config = {
            msg: '.observer__msg'
        }

        return {
            notify: function (index) {
                _$.msg = _$.element.querySelector(_config.msg);
                _$.msg.innerHTML = 'Observer ' + index + ' is notified!';
            }
        };
    };

    var Subject = function (element) {
        var _$ = {
            observers: [],
            element: element
        };

        function _getBtn() {
            _$.btn = _$.element.querySelector('.subject__btn');
        }
        function _addEvent() {
            _$.btn.addEventListener('click', function(event) {
                for (var i = 0; i < _$.observers.length; i++) {
                    _$.observers[i].notify(i);
                }
            }, false);
        }

        return {
            init: function() {
                _getBtn();
                _addEvent();
            },
            subscribeObserver: function (observer) {
                if (_$.observers !== null) {
                    _$.observers.push(observer);
                } else {
                    _$.observers = [];
                }

            },
            unsubscribeObserver: function (observer) {
                var index = _$.observers.indexOf(observer);
                if (index > -1) {
                    _$.observers.splice(index, 1);
                }
            },
            notifyObserver: function (observer) {
                var index = _$.observers.indexOf(observer);
                if (index > -1) {
                    _$.observers[index].notify(index);
                }
            },
            notifyAllObservers: function () {
                for (var i = 0; i < _$.observers.length; i++) {
                    _$.observers[i].notify(i);
                }
            }
        };
    };

    var subject = new Subject(subjectEl);

    for (var i = 0; i < observers.length; i++) {
        totObservers.push(new Observer(observers[i]));
    }

    for (var i = 0; i < observers.length; i++) {
        subject.subscribeObserver(totObservers[i]);
    }

    subject.init();

})();

Known Uses

Examples of the pattern found in real systems.
We include at least two examples from different domains.

  • What design patterns are closely related to this one?
  • What are the important differences?
  • With which other patterns should this one be used?

results matching ""

    No results matching ""