责任型模式一:Observer(观察者)模式
2013-10-12 22:01
78 查看
[b]目的: [/b]
Observer模式的宗旨是在多个对象之间定义一对多的关系,以便当一个对象状态改变时,其他所有依赖于这个对象的对象都能得到通知,并被自动更新。常用于业务逻辑层与表现层的分离。
[b]需求:由GUI引起的 [/b]
![](http://images.cnitblog.com/blog/494740/201310/12220019-129b39063efc46e9b46b7ef7ab0a0b4b.png)
图一
实现图一所示的图形界面。当滑动Slider时,界面中的两个曲线图像需要改变,底部的tPeak显示也需要改变。两个曲线由以下两个公式确定:
![](http://images.cnitblog.com/blog/494740/201310/12220019-c7228af8073342ca88b47626900c1fcd.png)
[b]最初的模型: [/b]
借助于Observer模式,当某个对象发生变化时,关注该对象的其他对象可以被通知。最初的类层次结构如图二。
![](http://images.cnitblog.com/blog/494740/201310/12220020-83f6ffe6a8d24bd2b464d4b713d1486b.png)
图二
上图中,ShowBallistics作为表现层元素,包含了burnPanel和thrustPanel这两个BallisticsPanel组件和一个slider滑动条组件,同时由于slider控制前台的显示,ShowBallistics实现了ChangeListener接口并在JSlider组件中注册,当JSlider发生变化时,JSlider依赖注册的ShowBallistics对象调用stateChanged(ChangeEvent e)方法,在该方法中,通过调用burnPanel和thrustPanel对象的setTPeak()方法重画曲线,调用valueLabel (JLabel)的setText()方法刷新显示。
分析这个应用, JSlider值改变引起burnPanel、thrustPanel和valueLabel这三个组件的重刷。根据上面的实现,表现层业务的重刷与业务逻辑层值的改变纠集在一个类当中。这显然是不合适的,简单的,当表现层的需求改变,如不再是画曲线而是画动画,就必须将BallisticsPanel组件改变为其他的显示组件,势必要对ShowBallistics类做出改变。因此我们引入基于Observer的MVC框架实现业务层与表现层的分离,使得两者能够独立变化,也能引起事件的响应。
与Bridge模式类比,以设备驱动为例,Bridge模式将具有一组类似接口的类提升出面向外部应用层调用的接口,实现了驱动具体实现与外部抽象逻辑(怎么用)的分离,方便驱动类的扩展,方便外部逻辑类的自由扩展。所以Bridge模式的关键在扩展,Observer模式的关键在通知。
[b]MVC架构: [/b]
综述的,随着应用程序和系统规模的膨胀,必须对责任进行分解和重分解,使每个类保持较小的规模,以便系统维护。
Model/View/Control是将对象与显示它的GUI(View/Control)分离。Java中,基于Observer(观察者)和Observable(被观察者)支持了Observer模式的标准实现。
分析本应用,实际上就是如何得到tPeak并以某几种方式显示tPeak的问题。因此在重构中,首先抽象出模型tPeak,如图三
![](http://images.cnitblog.com/blog/494740/201310/12220020-a6dfecdbc0d5480eb7afe2924d77f9e3.png)
图三
其中,depend on 关系表示在构造对象是需要传入Tpeak对象。Is Associated with关系表示是成员对象。在模型Tpeak中,当JSlider发生改变时,在stateChange方法中调用Tpeak的setValue方法,实现如下:
public void setValue(double value) {
this.value = value;
setChanged();
notifyObservers();
}
可以看到,Tpeak作为Observable,是Observer刷新操作的调用者,作为model,又是前台(JSlider)响应的接收者,可以视为完成了一次从前台到后台再到前台的过程。
对于Observable的底层实现,保持一个Observer的组合,实现一对多的依赖。涉及的操作,无非是增删改查以及触发事件的响应。
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
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() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
对于前台的Observer,在构造函数中向对应的Observable进行注册,发生响应时调用update()方法。
public class BallisticsLabel extends JLabel implements Observer {
public BallisticsLabel(Tpeak tPeak) {
tPeak.addObserver(this);
}
public void update(Observable obj, Object arg) {
setText(Format.formatToNPlaces(((Tpeak) obj).getValue(), 2));
repaint();
}
}
Observer模式的宗旨是在多个对象之间定义一对多的关系,以便当一个对象状态改变时,其他所有依赖于这个对象的对象都能得到通知,并被自动更新。常用于业务逻辑层与表现层的分离。
[b]需求:由GUI引起的 [/b]
![](http://images.cnitblog.com/blog/494740/201310/12220019-129b39063efc46e9b46b7ef7ab0a0b4b.png)
图一
实现图一所示的图形界面。当滑动Slider时,界面中的两个曲线图像需要改变,底部的tPeak显示也需要改变。两个曲线由以下两个公式确定:
![](http://images.cnitblog.com/blog/494740/201310/12220019-c7228af8073342ca88b47626900c1fcd.png)
[b]最初的模型: [/b]
借助于Observer模式,当某个对象发生变化时,关注该对象的其他对象可以被通知。最初的类层次结构如图二。
![](http://images.cnitblog.com/blog/494740/201310/12220020-83f6ffe6a8d24bd2b464d4b713d1486b.png)
图二
上图中,ShowBallistics作为表现层元素,包含了burnPanel和thrustPanel这两个BallisticsPanel组件和一个slider滑动条组件,同时由于slider控制前台的显示,ShowBallistics实现了ChangeListener接口并在JSlider组件中注册,当JSlider发生变化时,JSlider依赖注册的ShowBallistics对象调用stateChanged(ChangeEvent e)方法,在该方法中,通过调用burnPanel和thrustPanel对象的setTPeak()方法重画曲线,调用valueLabel (JLabel)的setText()方法刷新显示。
分析这个应用, JSlider值改变引起burnPanel、thrustPanel和valueLabel这三个组件的重刷。根据上面的实现,表现层业务的重刷与业务逻辑层值的改变纠集在一个类当中。这显然是不合适的,简单的,当表现层的需求改变,如不再是画曲线而是画动画,就必须将BallisticsPanel组件改变为其他的显示组件,势必要对ShowBallistics类做出改变。因此我们引入基于Observer的MVC框架实现业务层与表现层的分离,使得两者能够独立变化,也能引起事件的响应。
与Bridge模式类比,以设备驱动为例,Bridge模式将具有一组类似接口的类提升出面向外部应用层调用的接口,实现了驱动具体实现与外部抽象逻辑(怎么用)的分离,方便驱动类的扩展,方便外部逻辑类的自由扩展。所以Bridge模式的关键在扩展,Observer模式的关键在通知。
[b]MVC架构: [/b]
综述的,随着应用程序和系统规模的膨胀,必须对责任进行分解和重分解,使每个类保持较小的规模,以便系统维护。
Model/View/Control是将对象与显示它的GUI(View/Control)分离。Java中,基于Observer(观察者)和Observable(被观察者)支持了Observer模式的标准实现。
分析本应用,实际上就是如何得到tPeak并以某几种方式显示tPeak的问题。因此在重构中,首先抽象出模型tPeak,如图三
![](http://images.cnitblog.com/blog/494740/201310/12220020-a6dfecdbc0d5480eb7afe2924d77f9e3.png)
图三
其中,depend on 关系表示在构造对象是需要传入Tpeak对象。Is Associated with关系表示是成员对象。在模型Tpeak中,当JSlider发生改变时,在stateChange方法中调用Tpeak的setValue方法,实现如下:
public void setValue(double value) {
this.value = value;
setChanged();
notifyObservers();
}
可以看到,Tpeak作为Observable,是Observer刷新操作的调用者,作为model,又是前台(JSlider)响应的接收者,可以视为完成了一次从前台到后台再到前台的过程。
对于Observable的底层实现,保持一个Observer的组合,实现一对多的依赖。涉及的操作,无非是增删改查以及触发事件的响应。
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
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() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
对于前台的Observer,在构造函数中向对应的Observable进行注册,发生响应时调用update()方法。
public class BallisticsLabel extends JLabel implements Observer {
public BallisticsLabel(Tpeak tPeak) {
tPeak.addObserver(this);
}
public void update(Observable obj, Object arg) {
setText(Format.formatToNPlaces(((Tpeak) obj).getValue(), 2));
repaint();
}
}
相关文章推荐
- 责任型模式之Observer(观察者)模式
- Java开发中的23种设计模式之十五:观察者模式(Observer)
- 观察者模式 Observer
- Design Pattern_Observer(观察者模式)
- java: 观察者模式:Observable被观察者,Observer观察者
- 观察者模式之----Observable和Observer是怎么实现奇妙的通知功能的
- Android使用观察者模式Observer实现网络状态监听
- 5.7 观察者模式observer(行为模式)
- 观察者模式(Observer)
- 观察者模式2(observer)
- 设计模式学习笔记---观察者模式Observer pattern(Java版)
- C#设计模式02:观察者模式Observer Pattern
- 观察者模式(Observer Pattern)
- 观察者模式(Observer Pattern)
- C#设计模式之Observer观察者模式解决牛顿童鞋成绩问题示例
- Android设计模式之观察者模式 Observer
- 观察者模式(Observer)在Android中的应用:
- 观察者模式--Observer
- 观察者模式(Observer)
- 利用Observable、Observer实现观察者模式