javascript设计模式 - 通过公共方法回调

时间:2013-07-31 14:24:08

标签: javascript jquery design-patterns

我希望能够使用公共方法进行回调,而不是将其作为参数传递

,如

 function Car() {

    var that = this;

    this.onGearChanged = function(callback) {

       callback();
    }; 

   setTimeout(that.onGearChanged, 2000);
}

var car = new Car();
car.onGearChanged(function(){
   console.log("gear changed");

});

而不是

var onGearChanged = function(){
    console.log("gear changed")
}
var car = new Car(arg, arg, onGearChange);

我该怎么办呢?我应该遵循观察者模式吗?

2 个答案:

答案 0 :(得分:1)

代码将或多或少复杂,具体取决于您不明确的要求。如果您不需要,请不要使用图案,并且可以根据您的要求以多种方式调整图案。如果你真的不需要它,不要试图建立一个全面的解决方案。

如果您有很多观察员并且在汽车创建时了解它们,您可以使用

 function Car(onGearChangedArray) {
    this.triggerGearChanged = function() {
       for (var i=0;i<onGearChangedArray.length;i++) {
         onGearChangedArray[i]();
       }
    }; 
    window.setTimeout(this.triggerGearChanged,2000);
 }

 var car = new Car([function(){
   console.log("gear changed");
 }]);

如果你只有一个观察者,你就可以摆脱for循环。

但是如果你需要灵活地在运行时添加它们:

 function Car() {
    var onGearChangedCallbacks = [];
    this.onGearChanged = function(callback) {
       onGearChangedCallbacks.push(callback);
    };
    this.triggerGearChanged = function() {
       for (var i=0;i<onGearChangedCallbacks.length;i++) {
         onGearChangedCallbacks[i]();
       }
    }; 
    window.setTimeout(this.triggerGearChanged,2000);
 }

 var car = new Car();
 car.onGearChanged(function(){
   console.log("gear changed");
 });

或者如果你想将它抽象为下一个级别

 function Event() {
    var callbacks = [];
    this.bind = function(callback) {
       callbacks.push(callback);
    };
    this.fire = function() {
       for (var i=0;i<callbacks.length;i++) {
         callbacks[i]();
       }
    }; 
 }

 function Car() {
    this.gearChanged = new Event();
    window.setTimeout(this.gearChanged.fire,2000);
 }

 var car = new Car();
 car.gearChanged.bind(function(){
   console.log("gear changed");
 });

感谢Khanh TO的抽象概念,我只想在没有参数的情况下展示它。

您还可以考虑使用更复杂的东西,这样您就不需要自己编写此事件处理代码(如错误处理等),但同样,这取决于您的需求。您是否需要快速失败策略,或者是否应该记录错误?听众必须未注册吗?您是否可以陷入无限循环,因为triggerGearChanged可能导致另一个triggerGearChanged?你需要传递参数吗?请记住尽可能简单,所以如果你不需要传递参数,那么就不要这样做。

如果你喜欢unserscore.js,一个好的开始可能是http://mattmueller.me/blog/underscore-extension-observer-pattern

答案 1 :(得分:1)

我认为你需要这样的东西:

function Event(sender) {
    this._sender = sender;
    this._listeners = [];
}

Event.prototype = {
    attach: function (listener) {
        this._listeners.push(listener);
    },
    notify: function (args) {
        for (var i = 0; i < this._listeners.length; i++) {
            this._listeners[i](this._sender, args);
        }
    }
};

Car上课:

function Car(gear) {
     var self = this;

     self.Gear = gear;
     self.GearChanged = new Event(this);

     //Example method to trigger your GearChanged event. In your real code, you may have different logic
     self.changeGear = function (newGear){
         self.Gear = newGear;
         //notify all subscribers
         self.GearChanged.notify(newGear);
     }
}

订阅活动的示例代码:

var car = new Car("gear");
car.GearChanged.attach(function (sender,args){
    console.log("gear changed");
    console.log("new gear value is:" + args);
});
//do some logic that may trigger gearChanged event.
car.changeGear("new Gear");

您可以附加更多事件处理程序,并且将调用所有这些事件处理程序。您还可以使用此结构轻松添加更多事件,例如:tireChanged,..