观察者模式

2018-09-30  本文已影响0人  沐兮_d64c

1,概念

1)java.util.Observable(被观察者)和java.util.Observer(观察者),分别代表观察者模式中的Subject和Observer。
2)核心。 Observable/Subject中有包含一个观察者 Obsever的Vector列表,当Subject被观察者发生changed改变时,notifyObservers通知所有observer观察者。

2,JDK观察者模式的支持

1)被观察者

public class Observable {
    private boolean changed = false;//是否发生了改变
    private Vector<Observer> obs;//(线程安全的)维护观察者列表
    
    //添加、注册观察者。线程安全
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
}
    //删除观察者
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    
    //通知所有的观察者
    public void notifyObservers(Object arg) {
        //snapshot
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();//Indicates that this object has no longer changed
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);//call observer的update方法
    }

    protected synchronized void setChanged() {
        changed = true;
    }
    protected synchronized void clearChanged() {
        changed = false;
    }

2)观察者Observer

public interface Observer {
    //This method is called whenever the observed object is changed. 
    void update(Observable o, Object arg);
}

3,redis观察者模式(发布订阅功能)

1)pub、sub结构

image.png
publisher:通过 PUBLISH 命令向订阅者发送信息的客户端
subscriber:通过SUBSCRIBE 或者 PSUBSCRIBE 命令接收信息的客户端
channel:解耦发布者(publisher)和订阅者(subscriber)之间关系的中介

2)存储结构
订阅频道

struct redisServer { 
  // channlel - List<client>频道和订阅者client的列表
  dict *pubsub_channels; // Map channels to list of subscribed clients 
};
image.png
SUBSCRIBE命令:将客户端添加到channel的订阅链表中。
PSUBSCRIBE命令:订阅channel或者pattern,将客户端和订阅的模式添加到redisServer.pubsub_patterns 当中。
redisServer.pubsub_channels是一个channel-list<client>的字典。
redisServer.pubsub_patterns是一个链表。

订阅模式

struct redisServer { 
  list *pubsub_patterns; // A list of pubsub_patterns 
  };
typedef struct pubsubPattern { 
  redisClient *client; 
  robj *pattern; 
  } pubsubPattern;
image.png

3)使用 PUBLISH 命令向订阅者发送消息。

1)在 redisServer.pubsub_channels 字典中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。
2)遍历 redisServer.pubsub_patterns 链表,将链表中的模式和给定的频道进行匹配,如果匹配成功,那么将消息发布到相应模式的客户端当中。
3)publish pbkey "pbkey1"
subscribe pbkey
psubscribe pbkey
4)pubsub命令:redis2.8新增命令,客户端执行该命令,可以查看频道、模式的订阅信息。
pubsub channels [pattern]
pubsub numsub [channel-1]… :返回这些频道订阅者的数量。
pubsub numpat [pattern-1]… :返回这些频道订阅者的数量。

上一篇下一篇

猜你喜欢

热点阅读