louzhedong / blog

前端基础,深入以及算法数据结构

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

观察者模式

louzhedong opened this issue · comments

观察者模式

观察者模式,也叫发布订阅模式(Publish/subscribe),定义如下:

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新

在JavaScript中,一般用事件模式来替代传统的发布订阅模式

优点:时间上的解耦,对象间的解耦

缺点:对象间的逻辑被隐藏,难以追踪逻辑,消耗内存,如果事件不被使用,也会占用内存

实现
JavaScript
// 观察者模式(发布订阅模式)

var Event = (function () {
  var clientList = {};
  var listen = function (key, fn) {
    if (!clientList[key]) {
      clientList[key] = [];
    }
    clientList.push(fn);
  },

  var trigger = function () {
    var key = Array.prototype.shift.call(arguments),
      fns = clientList[key];
    if (!fns || fns.length === 0) {
      return false;
    }
    for (var i = 0, length = fns.length; i < length; i++) {
      fns[i].apply(this, arguments);
    }
  }

  return {
    listen,
    trigger
  }
})();

Event.listen('myfun', () => {});
Event.trigger('myfun');
Java
import java.util.Vector;

/**
 * 被观察者
 **/
public abstract class Subject {
    // 定义一个观察者数组
    private Vector<Observer> observers = new Vector<>();

    // 增加一个观察者
    public void addObserver(Observer observer) {
        this.observers.add(observer);
    }

    // 删除一个观察者
    public void removeObserver(Observer observer) {
        this.observers.remove(observer);
    }

    // 通知所有观察者
    public void notifyObservers() {
        for(Observer observer: this.observers) {
            observer.update();
        }
    }
}

/**
 * 具体的被观察者类
 **/
public class ConcreteSubject extends Subject{
    public void doSomething() {
        // do something
        super.notifyObservers();
    }
}

/**
 * 观察者
 **/
public interface Observer {
    // 更新方法
    void update();
}

/**
 * 具体的观察者类
 **/
public class ConcreteObserver implements Observer{
    @Override
    public void update() {

    }
}

/**
 * 实现类
 **/
public class Client {
    public static void main(String[] args) {
        // 创建观察者
        Observer observer = new ConcreteObserver();

        // 创建被观察者
        ConcreteSubject subject = new ConcreteSubject();

        subject.addObserver(observer);

        subject.doSomething();
    }
}