JavaScript 中的观察者设计模式


该系列的一部分:
JavaScript 设计模式

每个开发人员都努力编写可维护、可读和可重用的代码。随着应用程序变得更大,代码结构变得更加重要。设计模式证明对于解决这一挑战至关重要 – 在特定情况下为常见问题提供组织结构。

下面的设计模式只是可以帮助您升级为 JavaScript 开发人员的许多有用模式之一。有关完整集,请参阅JavaScript 设计模式

很多时候应用程序的一部分发生变化,其他部分需要更新。在 AngularJS 中,如果$scope对象更新,可以触发一个事件来通知另一个组件。观察者模式结合了这一点 – 如果一个对象被修改,它会向依赖对象广播发生了变化。

另一个主要示例是模型-视图-控制器 (MVC) 架构。当模型更改时,视图会更新。一个好处是将视图与模型解耦以减少依赖性。

观察者设计模式 维基百科上的观察者设计模式

正如在UML图所示,必要的对象是subjectobserver,和concrete对象。该主题包含对具体观察者的引用,以通知任何更改。Observer 对象是一个抽象类,它允许具体的观察者实现通知方法。

让我们看一个 AngularJS 示例,它通过事件管理包含观察者模式。

// Controller 1
$scope.$on('nameChanged', function(event, args) {
    $scope.name = args.name;
});

...

// Controller 2
$scope.userNameChanged = function(name) {
    $scope.$emit('nameChanged', {name: name});
};

对于观察者模式,重要的是区分独立的 object 或subject

需要注意的是,尽管观察者模式确实提供了许多优点,但缺点之一是随着观察者数量的增加,性能会显着下降。最臭名昭著的观察者之一是观察者在 AngularJS 中,我们可以观察变量、函数和对象。每当修改范围对象时$$digest循环都会运行并用新值通知每个观察者。

我们可以在 JavaScript 中创建我们自己的主题和观察者。让我们看看这是如何实现的:

var Subject = function() {
    this.observers = [];

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

var Observer = function() {
    return {
    notify: function(index) {
        console.log("Observer " + index + " is notified!");
    }
    }
}

var subject = new Subject();

var observer1 = new Observer();
var observer2 = new Observer();
var observer3 = new Observer();
var observer4 = new Observer();

subject.subscribeObserver(observer1);
subject.subscribeObserver(observer2);
subject.subscribeObserver(observer3);
subject.subscribeObserver(observer4);

subject.notifyObserver(observer2); // Observer 2 is notified!

subject.notifyAllObservers();
// Observer 1 is notified!
// Observer 2 is notified!
// Observer 3 is notified!
// Observer 4 is notified!

发布/订阅

然而,发布/订阅模式使用位于希望接收通知的对象(订阅者)和触发事件的对象(发布者)之间的主题/事件通道。此事件系统允许代码定义特定于应用程序的事件,这些事件可以传递包含订阅者所需值的自定义参数。这里的想法是避免订阅者和发布者之间的依赖关系。

这与观察者模式不同,因为任何订阅者都实现了适当的事件处理程序来注册和接收发布者广播的主题通知。

尽管存在区别,但许多开发人员选择将发布/订阅设计模式与观察者聚合在一起。发布/订阅模式中的订阅者通过某种消息传递媒介得到通知,但观察者通过实现类似于主题的处理程序得到通知。

在 AngularJS 中,订阅者使用 $on(‘event’, callback) ‘订阅’ 事件,发布者使用 $emit(‘event’, args) 或 $broadcast(‘event’, args) ‘发布’事件.

觉得文章有用?

点个广告表达一下你的爱意吧 !😁