Android使用的設計模式1——觀察者模式


  設計模式,對程序員來說是一個坎,想在程序員這條路走得更遠,設計模式是你的必修課。從大學時代接觸GoF到工作幾年后重新看設計模式,每次感覺都不一樣。這次想借着分析Android Framework源碼的機會,順道整理一下設計模式的知識。

  今天主要是先講一下觀察者模式,觀察者模式對於做系統或者做公共庫的朋友來說,應該很熟悉,基本上所有系統都會用到這個模式。整理的時候,主要是對模式進行進步講解然后結合Android里面應用進行說明。設計模式的說明主要是參考《研磨設計模式》這本書,這本書講解了GoF里面23種模式,而且比GoF更容易理解。如果對設計模式不了解的朋友,可以看看《研磨設計模式》這本書。

  結合Android源碼的時候,主要是針對應用層的代碼說明,而且盡量使用簡單例子代碼,所以不會出現太多Android系統級的代碼,大部分是我們做APP開發時會編寫的代碼。

  這篇文章不會詳細介紹設計模式,只是整理設計模式核心概念,結合Android應用說明。

  (PS:新建的QQ群,有興趣可以加入一起討論:Android群:322599434)

 

1、觀察者模式

  觀察者模式:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。這種模式最常用在我們熟悉的事件驅動模型里面,像VC、Android界面里面的事件響應,就是基於觀察者模式來實現。

  下面我們看看觀察者模式的類圖關系(圖片是截取《研磨設計模式》里面插圖):

 

 

 

  • Subject是我們定義目標對象,或者說被觀察對象。
  • ConcreteSubject是實際的被觀察對象。 
  • Observer是觀察者的接口,定義了回調接口。
  • ConcreteObserver是實際的觀察者對象。

 

2、觀察者模式含義

  下面講解一下個人對觀察者模式的理解,其實這個模式在我們平時工作中是很常用的模式,可能你已經使用過,缺沒有意識到。

  觀察者模式主要是針對一對多的數據更新。簡單來說就是,系統里面某個元素更新了數據,然后有好幾個元素是使用了這個元素的數據。此時更新了數據的對象,就要通知其他使用了它數據的對象,讓他們都進行更新。

  標准的觀察者對象是一對多的關系,不過我們都知道設計模式里面是很靈活,在我們使用的時候,經常需要進行變形。對現有的標准模式進行適當的修改來適應設計需求。

  在我們實際應用中,還會遇到一對一、或者多對一的情況。一對一就是,一個目標對應一個觀察者。多對一是指多個目標對應一個觀察者。

 

3、觀察者模式的簡單實現

  下面給出一個最簡單的觀察者模式實現代碼,把代碼看懂了,再回頭看文字講解,會比較容易理解。下面是目標對象的接口和實現代碼,只做了一個最簡單的接口。

//Edited by mythou
//http://www.cnblogs.com/mythou/
   //目標對象接口
    public interface Subject
    {
        //調用這個方法注冊一個新的觀察者對象
        public void attach(Observer observer);
        
        //調用這個方法刪除一個已注冊的觀察者對象
        public void detach(Observer observer);
        
        //調用這個方法通知所有注冊的觀察者對象
        void notifyObservers();
    }  
    
    //目標對象實現
    public class ConcreteSubject implements Subject
    {
    //向量容器,保存所有注冊的觀察者
private Vector observersVector = new Vector(); public void attach(Observer observer) { observersVector.addElement(observer); } public void detach(Observer observer) { observersVector.removeElement(observer); } public void notifyObservers() { Enumeration enumeration = observers(); while(enumeration.hasMoreElements()) { ((Observer)enumeration.nextElement()).update(); } } }

 

下面是觀察者的實現:

//Edited by mythou
//http://www.cnblogs.com/mythou/
   //觀察者接口
    public interface Observer
    {
        void update();
    }
    
    //觀察者實現
    public class ConcreteObserver implements Observer
    {
        public void update()
        {
            System.out.println("The subject has changed! mythou notify");
        }
    }

 

應用中使用的代碼:

 //Edited by mythou
//http://www.cnblogs.com/mythou/
  //客戶端
    public class Client
    {
        private static ConcreteSubject subject;
        private static Observer observer;
        
        public static void main(String args[])
        {
            //創建目標對象
            subject = new ConcreteSubject();
            //創建觀察者對象
            observer = new ConcreteObserver();
            subject.attach(observer);
            subject.change("mythou has changed data!");
        }
    }

 

4、Android 應用開發中的觀察者模式

  在我們做Android應用的時候,會大量使用觀察者模式,因為Framework層里面的事件驅動都是基於觀察者模式實現的。另外在Framework層里面的各種服務在數據變更的時候,也是通過觀察者模式實現上層數據更新。下面會講兩個例子來說明:

 A)控件中Listener監聽方式

  Android里面最典型的觀察者就是我們使用的各種控件監聽者。例如下面對某個按鈕的監聽:

 

//Edited by mythou
//http://www.cnblogs.com/mythou/
Button baiduclickButton = (Button)findViewById(R.id.button1);
//注冊觀察者 baiduclickButton.setOnClickListener(
new OnClickListener() {
  //觀察者實現 @Override
public void onClick(View arg0) { Log.d("Mythou_Log", "Click the button "); } });

 

  例如上面的代碼,注冊了一個按鈕的監聽方法。這里實際上是應用了一對一的觀察者模式,setOnClickListener()方法就是注冊一個觀察者,Button對象就是我們要觀察的目標對象。而new出來的OnClickListener(),就是我們實際的觀察者。

  每當我們的目標按鈕對象被點擊,狀態發生變化的時候,就會通過回調注冊的OnClickListener觀察者的onClick方法會來通知觀察者,Button狀態發生變化。這里的onClick相當於前面例子里面的update方法。下面是Android源碼里面對OnClickListener的定義,跟我們前面定義一個觀察者接口類似。

//Edited by mythou
//http://www.cnblogs.com/mythou/
  public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */
        void onClick(View v); }

 

B)GPS位置信息監聽

  上面對按鈕監聽是屬於一對一的觀察者模式,當然你也可以用一個Listener監聽多個按鈕。下面我們再講一個標准的一對多的觀察者模式的應用。在我們使用GPS模塊的時候,需要監聽GPS模塊位置變化,通常我們會編寫下面代碼:

 

 
         
//Edited by mythou
//http://www.cnblogs.com/mythou/
// 通過GPS定位
String LocateType= locationManager.GPS_PROVIDER;
Location location = locationManager.getLastKnownLocation(LocateType);
// 設置監聽器,設置自動更新間隔這里設置1000ms,移動距離:0米。
locationManager.requestLocationUpdates(provider, 1000, 0, locationListener);
// 設置狀態監聽回調函數。statusListener是監聽的回調函數。
locationManager.addGpsStatusListener(statusListener); 

//監聽器實現
private final GpsStatus.Listener statusListener = new GpsStatus.Listener() 
{
    public void onGpsStatusChanged(int event) 
  {
      // GPS狀態變化時的回調,獲取當前狀態
      GpsStatus status = locationManager.getGpsStatus(null);
    //自己編寫的方法,獲取衛星狀態相關數據
       GetGPSStatus(event, status);
    }
};

 

  GPS位置服務是Framework的一個系統層服務,整個系統只有一個運行的實例。但實際使用時,可能會出現好幾個應用都在使用這個服務,因此會形成了一個一對多的觀察者例子。這里不對代碼進行深入對比講解,只要對照上面的講解,你就可以把目標對象、觀察者接口、觀察者實現、數據更新回調接口找出來。有興趣的朋友還可以追查Android的源碼,看看GpsStatus里面的具體實現。

 

5、結語

  除了上面說的按鈕響應、GPS服務外,還有一個例子比較經典,就是我們的BroadcastReceiver響應,也是基於觀察者模式來實現,下面總結里面也會說到,觀察者模式支持廣播通信。有關BroadcastReceiver是怎么實現觀察者模式的,有興趣的朋友可以自己對比代碼,和查看Android實現源碼,自己動手才能加深印象。引入設計模式是為了對系統有更深入的理解。下面總結一下觀察者模式的優缺點,方便我們在使用的時候,可以根據實際情況衡量。

A)優點

  • 實現觀察者和目標對象之間的抽象耦合。
  • 觀察者模式支持廣播通信。被觀察者會所有的登記過的觀察者發出通知。

B)缺點

  • 可能會引起多余的數據通知。
  • 可能會導致通知數據循環,導致死鎖產生。

 

 

 

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3370340.html 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM