有很多Swing组建都是用MVC体系结构,其中Model层结合观察者模式通知所有观察该组件的对象。看JSlider类的部分源代码(其他的Swing组件有些是类似的):
public JSlider(int i, int j, int k, int l) { changeListener = createChangeListener(); sliderModel = new DefaultBoundedRangeModel(l, 0, j, k); sliderModel.addChangeListener(changeListener); updateUI(); } public JSlider(BoundedRangeModel boundedrangemodel) { changeListener = createChangeListener(); setModel(boundedrangemodel); sliderModel.addChangeListener(changeListener); updateUI(); }
构造器先new一个DefaultBoundedRangeModel类型的model,然后为它添加观察者,这里就是changeListener对象了,该对象是通过 createChangeListener()创建出来的,我们看看这个方法:
protected ChangeListener createChangeListener() { return new ModelListener(); }
private class ModelListener implements ChangeListener, Serializable { public void stateChanged(ChangeEvent changeevent) { fireStateChanged(); } final JSlider this$0; private ModelListener() { this$0 = JSlider.this; super(); } }
public void addChangeListener(ChangeListener changelistener) { listenerList.add(javax/swing/event/ChangeListener, changelistener); }
protected void fireStateChanged() { Object aobj[] = listenerList.getListenerList(); for(int i = aobj.length - 2; i >= 0; i -= 2) { if(aobj[i] != javax/swing/event/ChangeListener) continue; if(changeEvent == null) changeEvent = new ChangeEvent(this); ((ChangeListener)aobj[i + 1]).stateChanged(changeEvent); } }
观察者模式通常有4类参与者:
抽象主题(Subject):在这里就是BoundedRangeModel了
抽象观察者(Observer):ChangeListener
具体主题(ConcreteSubject):DefaultBoundedRangeModel
具体观察者(ConcreteObserver):ModelListener
在抽象主题接口中,通常定义addXXXListener(),removeXXXListener(),notifyAllListener()等方法,具体主题实现该接口,并维护一个Listener链表以使每个观察者都能得到通知。在抽象观察者中,定义update()方法,被具体观察者实现,主题变化时,调用该方法。
见惯了addActionListener()这类方法,都习以为常了,便很少去想为什么。看完JSlider的观察者模式,顿时恍然大悟,有时候,多多想想这些东西对巩固基础知识还是很有好处的。。