Home Web Front-end JS Tutorial Learn JavaScript design patterns Observer pattern_javascript skills

Learn JavaScript design patterns Observer pattern_javascript skills

May 16, 2016 pm 03:19 PM
javascript Observer pattern Design Patterns

1. Definition

Observer pattern (publish-subscribe pattern): It defines a one-to-many dependency relationship between objects. When the state of an object changes, all objects that depend on it will be notified.
In JavaScript, the event model is generally used to replace the traditional observer pattern.
Benefits:

  • (1) can be widely used in asynchronous programming and is an alternative to passing callback functions.
  • (2) can replace the hard-coded notification mechanism between objects. One object no longer needs to explicitly call an interface of another object. The two objects are easily decoupled.

2. DOM events – typical example of observer mode

We need to monitor the user's click action on document.body, but we have no way to predict when the user will click.
Therefore, we subscribe to the click event on document.body. When the body node is clicked, the body node publishes this message to the subscribers!

1

2

3

4

5

6

7

8

9

10

document.body.addEventListener("click", function() {

  console.log(1);

}, false);

 

// 可以多个订阅者

document.body.addEventListener("click", function() {

  console.log(2);

}, false);

 

doucment.body.click();

Copy after login

A certain website has header, nav navigation, message list and other modules. The rendering of these modules requires obtaining user login information.
(1) General writing:

1

2

3

4

5

6

7

8

9

10

11

12

13

$.ajax({

  url: './login',

  type: 'post',

  contentType: 'application/json',

  dataType:'json',

  success: function(data) {

    if(data.status === "success") {

      // 登录成功,渲染header、nav

      header.setInfo(data.headerInfo);

      nav.setInfo(data.navInfo);

    }

  }

});

Copy after login

(2) Using the observer pattern, it is easy to decouple!

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

$.ajax({

  ...,

  success: function(data) {

    if(data.status === "success") {

      // 登录成功,发布登陆成功消息

      login.trigger("loginsuccess", data);

    }

  }

});

 

var header = (function() {

  // 监听消息

  login.listen("loginsuccess", function(data){

    header.setInfo(data.headerInfo);

  });

  return {

    setInfo: function(data) {

      console.log("设置header信息");

    }

  };

})();

 

var nav = (function() {

  login.listen("loginsuccess", function(data){

    nav.setInfo(data.navInfo);

  });

  return {

    setInfo: function(data) {

      console.log("设置nav信息");

    }

  }

})();

Copy after login

3. Universal Observer Mode

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

/*

 * 示例:

 * Event.create("namespace1").listen('click', function(a){

 *   console.log(a);

 * });

 * Event.create("namespace1").trigger("click", 1);

 */

var Event = (function() {

  var global = this,

    Event,

    _default = 'default';

 

  Event = function() {

    var _listen,

      _trigger,

      _remove,

      _slice = Array.prototype.slice,

      _shift = Array.prototype.shift,

      _unshift = Array.prototype.unshift,

      namespaceCache = [],

      _create,

      find,

      each = function( ary, fn) {

        var ret;

        for(var i = 0, l = ary.length; i < l; i++) {

          var n = ary[i];

          ret = fn.call(n, i, n);

        }

        return ret;

      };

    // 订阅

    _listen = function(key, fn, cache) {

      if(!cache[key]) {

        cache[key] = [];

      }

      cache[key].push(fn);

    };

    // 移除订阅

    _remove = function(key, cache, fn) {

      if(cache[key]) {

        if(fn) {

          for(var i = cache[key].length; i >=0; i++) {

            if(cache[key][i] === fn) {

              cache[key].splice(i, 1);

            }

          }

        }else {

          cache[key] = [];

        }

      }

    };

    // 发布

    _trigger = function() {

     var cache = _shift.call(arguments),

       key = _shift.call(arguments),

       args = arguments,

       _self = this,

       ret,

       stack = cache[key];

      if(!stack || !stack.length) {

        return;

      }

      return each(stack, function() {

        return this.apply(_self, args);

      });

    };

    // 创建命名空间

    _create = function(namespace) {

      var namespace = namespace || _default;

      var cache = {},

        offlineStack = [], // 离线事件

        ret = {

          listen: function (key, fn, last) {

            _listen(key, fn, cache);

            if (offlineStack == null) {

              return;

            }

            if (last === 'last') {

              offlineStack.length && offlineStack.pop()();

            } else {

              each(offlineStack, function () {

                this();

              });

            }

            offlineStack = null;

          },

 

          one: function (key, fn, last) {

            _remove(key, cache);

            this.listen(key, fn, last);

          },

 

          remove: function(key, fn, last) {

            _remove(key, cache, fn);

          },

 

          trigger: function() {

            var fn,

              args,

              _self = this;

            _unshift.call(arguments, cache);

            args = arguments;

            fn = function() {

              return _trigger.apply(_self, args);

            };

            if(offlineStack) {

              return offlineStack.push(fn);

            }

            return fn;

          }

        };

 

        return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;

      };

 

    return {

      create: _create,

      one: function(key, fn, last) {

        var event = this.create();

        event.one(key, fn, last);

      },

      remove: function(key, fn) {

        var event = this.create();

        event.remove(key, fn);

      },

      listen: function(key, fn, last) {

        var event = this.create();

        event.listen(key, fn, last);

      },

      trigger: function() {

        var event = this.create();

        event.trigger.apply(this, arguments);

      }

    };

  }();

  return Event;

})();

Copy after login

I hope this article will be helpful to everyone learning JavaScript programming.

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot Article Tags

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

The difference between design patterns and architectural patterns in Java framework The difference between design patterns and architectural patterns in Java framework Jun 02, 2024 pm 12:59 PM

The difference between design patterns and architectural patterns in Java framework

The wonderful use of the adapter pattern in Java design patterns The wonderful use of the adapter pattern in Java design patterns May 09, 2024 pm 12:54 PM

The wonderful use of the adapter pattern in Java design patterns

Analysis of the Decorator Pattern in Java Design Patterns Analysis of the Decorator Pattern in Java Design Patterns May 09, 2024 pm 03:12 PM

Analysis of the Decorator Pattern in Java Design Patterns

PHP design pattern practical case analysis PHP design pattern practical case analysis May 08, 2024 am 08:09 AM

PHP design pattern practical case analysis

What are the advantages and disadvantages of using design patterns in java framework? What are the advantages and disadvantages of using design patterns in java framework? Jun 01, 2024 pm 02:13 PM

What are the advantages and disadvantages of using design patterns in java framework?

PHP Design Patterns: Test Driven Development in Practice PHP Design Patterns: Test Driven Development in Practice Jun 03, 2024 pm 02:14 PM

PHP Design Patterns: Test Driven Development in Practice

Application of design patterns in Guice framework Application of design patterns in Guice framework Jun 02, 2024 pm 10:49 PM

Application of design patterns in Guice framework

How design patterns deal with code maintenance challenges How design patterns deal with code maintenance challenges May 09, 2024 pm 12:45 PM

How design patterns deal with code maintenance challenges

See all articles