设计模式之观察者模式

前端之家收集整理的这篇文章主要介绍了设计模式之观察者模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

情景:

气象站会实时发布气象数据,要求创建布告板,并把气象站发布的数据显示出来。

布告板会有很多,随时回添加一个或删除一个,而每个布告板显示的格式也不尽相同。

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知自动更新。

被观察对象称作主题(Subject),依赖主题的对象称作观察者(Observer)。

当两个对象之间松耦合,它们依然可以交互,但是不太清除彼此之间的细节。

观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

类图: 

设计原则:为了交互对象之间的松耦合设计而努力。

气象站的实现:

主题接口:

观察者接口:

update( temp, humidity,

主题(气象站)实现:

<span style="color: #0000ff;">public <span style="color: #0000ff;">class WeatherData <span style="color: #0000ff;">implements<span style="color: #000000;"> Subject {

</span><span style="color: #0000ff;"&gt;private</span> ArrayList<Observer><span style="color: #000000;"&gt; observers;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; temperature;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; humidity;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; pressure;

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; WeatherData() {
    observers </span>= <span style="color: #0000ff;"&gt;new</span> ArrayList<><span style="color: #000000;"&gt;();
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; registerObserver(Observer o) {
    observers.add(o);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; removeObserver(Observer o) {
    </span><span style="color: #0000ff;"&gt;int</span> i =<span style="color: #000000;"&gt; observers.indexOf(o);
    </span><span style="color: #0000ff;"&gt;if</span> (i >= 0<span style="color: #000000;"&gt;) {
        observers.remove(i);
    }
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; notifyObservers() {
    </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> i = 0; i < observers.size(); i++<span style="color: #000000;"&gt;) {
        Observer observer </span>=<span style="color: #000000;"&gt; observers.get(i);
        observer.update(temperature,humidity,pressure);
    }
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; measurementsChanged() {
    notifyObservers();
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span> setMeasurements(<span style="color: #0000ff;"&gt;float</span> temperature,<span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; pressure) {
    </span><span style="color: #0000ff;"&gt;this</span>.temperature =<span style="color: #000000;"&gt; temperature;
    </span><span style="color: #0000ff;"&gt;this</span>.humidity =<span style="color: #000000;"&gt; humidity;
    </span><span style="color: #0000ff;"&gt;this</span>.pressure =<span style="color: #000000;"&gt; pressure;
    measurementsChanged();
}

}

观察者(布告板)实现:

<span style="color: #0000ff;">public <span style="color: #0000ff;">class CurrentConditionsDisplay <span style="color: #0000ff;">implements<span style="color: #000000;"> Observer,DisplayElement {

</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; temperature;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; humidity;
</span><span style="color: #0000ff;"&gt;private</span><span style="color: #000000;"&gt; Subject weatherData;

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; CurrentConditionsDisplay(Subject weatherData) {
    </span><span style="color: #0000ff;"&gt;this</span>.weatherData =<span style="color: #000000;"&gt; weatherData;
    weatherData.registerObserver(</span><span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; display() {
    System.out.println(</span>"Current conditions: " + temperature + 
            "F degrees and " + humidity + "% humdity."<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span> update(<span style="color: #0000ff;"&gt;float</span> temperature,<span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; pressure) {
    </span><span style="color: #0000ff;"&gt;this</span>.temperature =<span style="color: #000000;"&gt; temperature;
    </span><span style="color: #0000ff;"&gt;this</span>.humidity =<span style="color: #000000;"&gt; humidity;
    display();
}

}
……………………
<span style="color: #0000ff;">public <span style="color: #0000ff;">class ChineseDisplay <span style="color: #0000ff;">implements<span style="color: #000000;"> Observer,DisplayElement {
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> temperature;
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> humidity;
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> pressure;
<span style="color: #0000ff;">private<span style="color: #000000;"> Subject weatherData;

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; ChineseDisplay(Subject data) {
    </span><span style="color: #0000ff;"&gt;this</span>.weatherData =<span style="color: #000000;"&gt; data;
    weatherData.registerObserver(</span><span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; display() {
    System.out.println(</span>"天气状况: 气温:" + temperature + 
            "F, 湿度:" + humidity + "%, 气压:" + pressure + " Pa。"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span> update(<span style="color: #0000ff;"&gt;float</span> temperature,<span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; pressure) {
    </span><span style="color: #0000ff;"&gt;this</span>.temperature =<span style="color: #000000;"&gt; temperature;
    </span><span style="color: #0000ff;"&gt;this</span>.humidity =<span style="color: #000000;"&gt; humidity;
    </span><span style="color: #0000ff;"&gt;this</span>.pressure =<span style="color: #000000;"&gt; pressure;
    display();
}

}

测试类:

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; main(String[] args) { WeatherData weatherData </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; WeatherData(); CurrentConditionsDisplay conditionsDisplay </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; CurrentConditionsDisplay(weatherData); StatisticsDisplay statisticsDisplay </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; StatisticsDisplay(weatherData); ChineseDisplay chineseDisplay </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; ChineseDisplay(weatherData); weatherData.setMeasurements(</span>80,65,30.4f<span style="color: #000000;"&gt;); System.out.println(); weatherData.setMeasurements(</span>82,70,29.2f<span style="color: #000000;"&gt;); System.out.println(); weatherData.setMeasurements(</span>78,90,29.2f<span style="color: #000000;"&gt;); }

}

输出

Current conditions: 80.0F degrees and 65.0%80.0F, 湿度:65.0%, 气压:30.4Current conditions: 82.0F degrees and 70.0%<span style="color: #000000;"> humdity.
天气状况: 气温:
82.0F, 湿度:70.0%, 气压:29.2 Pa。

Java中自带Observable类和Observer类,可以通过继承这两个类来实现观察者模式

主题

<span style="color: #0000ff;">public <span style="color: #0000ff;">class WeatherData <span style="color: #0000ff;">extends<span style="color: #000000;"> Observable {
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> temperature;
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> humidity;
<span style="color: #0000ff;">private <span style="color: #0000ff;">float<span style="color: #000000;"> pressure;

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; WeatherData() {}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; measurementsChanged() {
    setChanged();
    notifyObservers();
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span> setMeasurements(<span style="color: #0000ff;"&gt;float</span> temperature,<span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; pressure) {
    </span><span style="color: #0000ff;"&gt;this</span>.temperature =<span style="color: #000000;"&gt; temperature;
    </span><span style="color: #0000ff;"&gt;this</span>.humidity =<span style="color: #000000;"&gt; humidity;
    </span><span style="color: #0000ff;"&gt;this</span>.pressure =<span style="color: #000000;"&gt; pressure;
    measurementsChanged();
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; getTemperature() {
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; temperature;
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; getHumidity() {
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; humidity;
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; getPressure() {
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; pressure;
}

}

观察Observable源码setChanged方法

=

有时候改变需要自己定义,比如温度改变0.5℃以上才算改变等……

notifyObservers方法的实现:

</span><span style="color: #0000ff;"&gt;synchronized</span> (<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;if</span> (!<span style="color: #000000;"&gt;changed) </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt;; arrLocal </span>=<span style="color: #000000;"&gt; obs.toArray(); clearChanged(); } </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;int</span> i = arrLocal.length-1; i>=0; i--<span style="color: #000000;"&gt;) ((Observer)arrLocal[i]).update(</span><span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;,arg); }</span></pre>

布告板的实现:

<span style="color: #0000ff;">public <span style="color: #0000ff;">class CurrentConditionsDisplay <span style="color: #0000ff;">implements<span style="color: #000000;"> Observer,DisplayElement {

</span><span style="color: #0000ff;"&gt;private</span><span style="color: #000000;"&gt; Observable observable;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; temperature;
</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;float</span><span style="color: #000000;"&gt; humidity;

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; CurrentConditionsDisplay(Observable observable) {
    </span><span style="color: #0000ff;"&gt;this</span>.observable =<span style="color: #000000;"&gt; observable;
    observable.addObserver(</span><span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; display() {
    System.out.println(</span>"Current conditions: " + temperature + 
            "F degrees and " + humidity + "% humdity."<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; update(Observable obs,Object arg) {
    </span><span style="color: #0000ff;"&gt;if</span> (obs <span style="color: #0000ff;"&gt;instanceof</span><span style="color: #000000;"&gt; WeatherData) {
        WeatherData weatherData </span>=<span style="color: #000000;"&gt; (WeatherData) obs;
        </span><span style="color: #0000ff;"&gt;this</span>.temperature =<span style="color: #000000;"&gt; weatherData.getTemperature();
        </span><span style="color: #0000ff;"&gt;this</span>.humidity =<span style="color: #000000;"&gt; weatherData.getHumidity();
        display();
    }
}

}

这里的update()方法和上面的实现不同,上面的实现是push的方法,也就是主题把数据直接送到观察者那里。而这里的是观察者通过getter()方法来自己pull所需要的数据。

但是java.util.Observable和java.util.Observer都是类而不是接口,所以要继承它们就无法继承别的类了。

JDK中的观察者模式

Swing中的JButton就用到了观察者模式。

<span style="color: #0000ff;">import<span style="color: #000000;"> javax.swing.JButton;
<span style="color: #0000ff;">import
<span style="color: #000000;"> javax.swing.JFrame;

<span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> SwingObserverExample {
JFrame frame;

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; main(String[] args) {
    SwingObserverExample example </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; SwingObserverExample();
    example.go();
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; go() {
    frame </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; JFrame();

    JButton button </span>= <span style="color: #0000ff;"&gt;new</span> JButton("Should I do it?"<span style="color: #000000;"&gt;);
    button.addActionListener(</span><span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; AngelListener());
    button.addActionListener(</span><span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; DevilListener());
    frame.getContentPane().add(BorderLayout.CENTER,button);
    frame.setSize(</span>200,200<span style="color: #000000;"&gt;);
    frame.setVisible(</span><span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;);
}
</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 一个ActionListener就是一个观察者</span>
<span style="color: #0000ff;"&gt;class</span> AngelListener <span style="color: #0000ff;"&gt;implements</span><span style="color: #000000;"&gt; ActionListener {
    @Override
    </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; actionPerformed(ActionEvent e) {
        System.out.println(</span>"Dont do it,you might regret it!"<span style="color: #000000;"&gt;);
    }
}


</span><span style="color: #0000ff;"&gt;class</span> DevilListener <span style="color: #0000ff;"&gt;implements</span><span style="color: #000000;"&gt; ActionListener {
    @Override
    </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; actionPerformed(ActionEvent e) {
        System.out.println(</span>"Come on,do it!"<span style="color: #000000;"&gt;);
    }
}

}

原文链接:https://www.f2er.com/javaschema/69832.html

猜你在找的设计模式相关文章