• 观察者模式

    观察者模式

    观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

    定义一个目标构造函数,并实现绑定、解绑和触发等方法:

    1. function Subject() {
    2. this.events = {};
    3. this.count = 0;
    4. }
    5. Subject.prototype.on = function( type, handler ) {
    6. var events = this.events;
    7. var token = (++this.count).toString();
    8. if ( !events[type] ) {
    9. events[type] = [];
    10. }
    11. events[type].push({
    12. token: token,
    13. handler: handler
    14. });
    15. return token;
    16. }
    17. Subject.prototype.off = function( token ) {
    18. var events = this.events;
    19. var type, i, l, observers;
    20. for ( type in events ) {
    21. observers = events[type];
    22. for ( i = 0, l = observers.length; i < l; i++ ) {
    23. if ( observers[i].token === token ) {
    24. observers.splice(i, 1);
    25. return token;
    26. }
    27. }
    28. }
    29. return false;
    30. }
    31. Subject.prototype.trigger = function( type, args ) {
    32. var observers = this.events[type];
    33. if ( !observers ) {
    34. return;
    35. }
    36. var length = observers.length;
    37. while ( length-- ) {
    38. observers[length].handler(type, args);
    39. }
    40. }

    实例化一个目标并进行三次绑定操作,其中两次用同一个主题,即共两个主题:

    1. var pub = new Subject();
    2. var sub1, sub2, sub3;
    3. var w1 = 'JavaScript Weekly';
    4. var w2 = 'Web Design Weekly';
    5. sub1 = pub.on(w1, function( type, title ) {
    6. console.log('%s (%s): %s', type, sub1, title);
    7. });
    8. sub2 = pub.on(w1, function( type, title ) {
    9. console.log('%s (%s): %s', type, sub2, title);
    10. });
    11. sub3 = pub.on(w2, function( type, title ) {
    12. console.log('%s (%s): %s', type, sub3, title);
    13. });
    14. pub.trigger(w1, 'Celebrating 10 Years of the V8 JavaScript engine');
    15. pub.trigger(w2, 'The \'Capable Web\': A 10 Year Retrospective');

    在分别触发那两个被绑定的主题后,控制台输出了三条信息。

    将绑定两次的主题进行一次解绑操作后再次触发该主题:

    1. pub.off(sub2);
    2. pub.trigger(w1, 'Celebrating 10 Years of the V8 JavaScript engine');

    控制台中只输出一条信息。