首页 > 代码库 > Observer,Observable实现观察者模式

Observer,Observable实现观察者模式

(#)个人对于观察者的理解:观察者与发布订阅模式是非常的相似的,例如当多个威信使用者订阅了同一个主题之后,那么这个主题就是一个被观察者,而这些用户就是观察

者,当这个主题更新了新的内容以后,就要通知所有的观察者,主题更新了新的内容了

 

(#)TaLK IS CHEEP    场景:服务器解析DNS

1.抽象一个域名解析服务,实现java.util的Observer与Observable

/**
 * Author: scw
 * Time: 16-12-28
 */
public abstract class DnsServer extends Observable implements Observer{

    public void update(Observable o, Object arg) {
        Recorder recorder = (Recorder) arg;
        if(isLocal(recorder)){
            recorder.setIp(getIPAddress());
            sign(recorder);
        }else{
            responseFromUpperServer(recorder);
        }
    }

    /**
     * 增加观察者
     */
    public void setUpperServer(DnsServer dnsServer){
        super.deleteObservers();
        super.addObserver(dnsServer);
    }
    /**
     * 向父dns请求解析,通知观察者
     */
    private void responseFromUpperServer(Recorder recorder){
        super.setChanged();
        super.notifyObservers(recorder);
    }

    public abstract void sign(Recorder recorder);

    public abstract boolean isLocal(Recorder recorder);

    public String getIPAddress(){
        return "127.0.1.1";
    }
}

2.三个具体的域名解析服务

/**
 * Author: scw
 * Time: 16-12-28
 */
public class SHDnsServer extends DnsServer {
    @Override
    public void sign(Recorder recorder) {
        recorder.setOwner("上海服务器");
    }

    @Override
    public boolean isLocal(Recorder recorder) {
        return StringUtils.endsWith(recorder.getDomain(),".sh");
    }
}

/**
 * Author: scw
 * Time: 16-12-28
 */
public class ChinaDnsServer extends DnsServer {
    @Override
    public void sign(Recorder recorder) {
        recorder.setOwner("中国服务器");
    }

    @Override
    public boolean isLocal(Recorder recorder) {
        return StringUtils.endsWith(recorder.getDomain(),".cn");
    }
}

/**
 * Author: scw
 * Time: 16-12-28
 */
public class TopDnsServer extends DnsServer {
    @Override
    public void sign(Recorder recorder) {
        recorder.setOwner("世界");
    }

    @Override
    public boolean isLocal(Recorder recorder) {
        return StringUtils.endsWith(recorder.getDomain(),".www");
    }
}

3.ok,上面的步奏都实现了的话,那么接下来随便写一个main方法测试一下就好了,这个很easy,那么大家应该很好奇这两个接口都干了什么呢?下面解析一下

(#)接口解析

1.ObServer,其实这个接口很简单,内部只有一个update方法,所以实现的重点不在这里

技术分享

 

2.Observable类,看过源码之后,发现这个类是线程安全的,使用了Vector来存储,所有的观察者,同时对于change的设置也是同步的

下面来看一下关键一个notifyObservers方法:

技术分享

看见了吧,这个方法的关键就是最后一行代码,也就是说一个观察者的类应该去实现这Observer接口,重写里面的update方法,那么在被观察者做出改变的时候就能很

简单的通知到观察者的update方法。

(#)最后这个接口其实很简单,但是其中涉及到的设计模式还是很值得参考的,而且以前写这种模式的时候也一直是自己来实现,从来发现原来java本身就给我们实现了

这些接口

Observer,Observable实现观察者模式