天天看點

Observer(觀察者)模式一

Observer模式的宗旨是在多個對象之間定義一對多的關系,以便當一個對象狀态改變的時候,其他所有依賴于這個對象的對象都能夠得到通知,并被自動更新。

1.經典範例:

   借助于Observer模式,當某個對象發生變化時,關注該對象的其他對象可以被通知。這種模式的一個最常見的例子是圖形使用者界面。每當圖形界面的使用者單擊按鈕或者調整滑動條的時候,該應用程式中許多對象都會對此做出反應。Java開發者假定應用程式都會關心圖形界面使用者何時改變GUI元件。很顯然,Observer模式在Java Swing庫中得到了廣泛應用。在Java Swing架構中,關注Swing元件變化的類被稱為“監聽器”。我們可以為自己關心的每個事件注冊一個監聽器,以便元件事件發生的時候,我們能夠得到通知。

ShowBallistics類和BallisticsPanel類位于app.observer.ballistics包中。BallisticsFunction接口位于com.oozinoz.ballistics包中,它定義了燃燒速率和推進力曲線。該Java包中還有一個Ballisticstics工具類,它實作了BallisticsFunction接口。

這個彈道學應用程式在初始化滑動條的時候,将自己注冊為滑動條事件的監聽器。當滑動條滑動的時候,該應用程式就會更新用于顯示曲線的面闆和用于顯示tpeak值的标簽。

Observer(觀察者)模式一

習題1:請完成ShowBallistics類的slider()方法和stateChanged()方法,該繪圖面闆和tpeak标簽能夠根據滑動條值的改變而顯示不同的曲線和資料。

public JSlider slider() 

{ if(slider == null) 

{ slider = new JSlider(); 

sliderMax = slider.getMaximum(); 

sliderMin = slider.getMinimum();

 slider.addChangeListener(this); 

slider.setValue(slider.getMinimum());

 }

 return slider; 

} 



public void stateChanged(ChangeEvent e) 

{ double val = slider.getValue();

 double tp = (val - sliderMin)/(sliderMax - sliderMin);

 burnPanel().setTPeak(tp); 

thrustPanel().setTPeak(tp);

 valueLabel().setText(Format.formatToNPlace(N,2); 

} 

           

ShowBallistics類根據滑動條的值更新燃燒速率面闆、推進力面闆以及顯示tpeak值的标簽。這種設計方式很常見,雖然它不是很糟糕,但值得注意的是,它與Observer模式的意圖完全相悖!Java Swing架構采用Observer模式,以便滑動條無需了解那些使用者關注自己。但是ShowBallistics使我們重新面臨這種本希望避免的狀況:将單個依賴滑動條元件的對象---即它自身--注冊為滑動條事件的監聽器,在得到滑動條事件通知之後,該對象又将事件分發給各個相關的對象。在這種設計方式中,該對象必須清楚哪些對象依賴于滑動條元件,而這些依賴滑動條元件的對象并沒有注冊自己以監聽滑動條事件。

     為了與Observer模式的意圖保持一緻,我們可以對上面的代碼進行一下改動,進而讓關注滑動條變化的元件直接注冊自己以監聽滑動條事件。這種新的設計的類圖如下:

Observer(觀察者)模式一

在新的設計中,我們可以将addChangeListener()方法的調用從slider()方法中移出來,移到各個依賴滑動條的元件的構造器中:

public BallisticsPanel2(BallisticsFunction func,JSlider slider)
{
     this.func = func;
     this.slider = slider;
     slider.addChangeListener(this);
}
           

   每當滑動條滑動BallisticsPanel2類對象便會得到通知,然後标簽會重新計算并顯示tpeak值:

繼續閱讀