Java设计模式之观察者模式详解

观察者模式,是一对多的关系,一个主题对应多个观察者,当这个主题发生变化的时候,全部观察着这个主题的观察者都会接收到通知来获悉主题的变化。

在现实中咱们也会遇到许许多多应用观察者模式的行为,好比电视的节目频道里有时候会有暴雨天气的标志,这个标志是会随着天气的变化来显示,而咱们显示的也是最新的天气标志,在这里电视频道就至关因而一个主题,而咱们的电视机就是这个主题观察者,因此当这个天气标志有变化时电视上的画面也随着变化。这就是使用的观察者模式,下面就让咱们用代码实现观察者模式。ide


首先咱们须要定义主题的接口,这里面有三个方法,registerObserver、removeObserver和notifyObserver,分别是用来添加观察者、去除观察者和通知全部观察者。其中dataChange方法是只要当数据有变化就会被调用,咱们须要在这个方法里调用notifyObserver去通知全部的观察者数据变化的内容,这里咱们使用setSimulateDataChange方法来模拟数据的变化。测试

public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObserver();
}

而后咱们建立一个具体的主题类来实现这个主题接口,假设这个类是获取电视频道的信息。在这个类里面咱们须要建立一个集合用来存取观察这个主题的全部观察者,接口中的registerObserver和removeObserver方法实际就是对集合的增删操做,而notifyObserver方法其实就是遍历集合通知全部的对象。this

public class TelevisionData implements Subject {
    private String showName;
    private String showType;
    private ArrayList<Observer> list;

    public TelevisionData(){
        list = new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        int index = list.indexOf(observer);
        if (index>=0){
            list.remove(index);
        }
    }

    @Override
    public void notifyObserver() {
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
        Observer observer = (Observer)listIterator.next();
            observer.update(showName,showType);
        }
    }

    public void dataChange(){
        notifyObserver();
    }

    //此方法用于模拟控制数据的更新,数据更新后会调用dataChange方法
    public void setSimulateDataChange(String showName,String showType){
         this.showName = showName;
         this.showType= showType;
         dataChange();
    }
}

主题部分的代码写好了,接着咱们须要写观察者的代码,电视节目都播放在电视上,那咱们把建立的电视类抽取出一个show方法放在Display接口中。code

public interface Display {
    void show();
}

另外观察者还有一个共性,就是要接收更新到的数据进行更新,因此咱们再抽取出一个update方法放到Obeserver接口中。视频

public interface Observer {
    void update(String showName,String showNum);
}

最后咱们建立观察者的类来实现这两个接口,在这个类中showName和showType字段是用来接收主题的数据的,而subject则是要关注的主题类型引用,经过这个引用咱们就能够调用registerObserver和removeObserver来控制观察者是否还要观察这个主题。当主题更新时则会调用update方法,观察者获取到更新的数据就再调用show方法显示出来。server

public class John implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public John(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("john收看的当前天气类型-" + showType);
        System.out.println("john收看的当前天气级别-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }
}

public class Jack implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public Jack(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("jack收看的当前天气类型-" + showType);
        System.out.println("jack收看的当前天气级别-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }

}

下面咱们来测试一下对象

//建立一个主题
televisionData = new TelevisionData();
    
//添加观察者
John john = new John(televisionData);
john.registerObserver();
Jack jack = new Jack(televisionData);
jack.registerObserver();
        
//模拟数据更新
changeData("大风", "5级");
changeData("暴雨", "红色");
    
public static void changeData(String showName, String showType) {
    televisionData.setSimulateDataChange(showName,showType);
}

结果:
john收看的当前天气类型-红色
john收看的当前天气级别-暴雨
jack收看的当前天气类型-红色
jack收看的当前天气级别-暴雨
john收看的当前天气类型-5级
john收看的当前天气级别-大风
jack收看的当前天气类型-5级
jack收看的当前天气级别-大风接口


咱们再试着去掉一个观察者看它还会不会收到更新,结果是不会收到更新了rem

changeData("暴雨", "红色");
john.removeObserver();
changeData("大风", "5级");

结果:
john收看的当前天气类型-红色
john收看的当前天气级别-暴雨
jack收看的当前天气类型-红色
jack收看的当前天气级别-暴雨
jack收看的当前天气类型-5级
jack收看的当前天气级别-大风io


总结:观察者模式的大体原理其实就是观察者持有主题的引用来控制主题内部的集合对本身增删从而控制是否关注这个主题,而主题则经过对集合中的对象的操做,把数据的更新通知给全部的观察者。

相关文章
相关标签/搜索