10、觀察者模式

觀察者模式

模式的定義與特色

觀察者(Observer)模式的定義:指多個對象間存在一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。這種模式有時又稱做發佈-訂閱模式、模型-視圖模式,它是對象行爲型模式。java

觀察者模式是一種對象行爲型模式,其主要優勢以下。測試

  1. 下降了目標與觀察者之間的耦合關係,二者之間是抽象耦合關係。
  2. 目標與觀察者之間創建了一套觸發機制。

它的主要缺點以下。設計

  1. 目標與觀察者之間的依賴關係並無徹底解除,並且有可能出現循環引用。
  2. 當觀察者對象不少時,通知的發佈會花費不少時間,影響程序的效率。

模式的結構

實現觀察者模式時要注意具體目標對象和具體觀察者對象之間不能直接調用,不然將使二者之間緊密耦合起來,這違反了面向對象的設計原則。code

觀察者模式的主要角色以下。server

  1. 抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用於保存觀察者對象的彙集類和增長、刪除觀察者對象的方法,以及通知全部觀察者的抽象方法。
  2. 具體主題(Concrete Subject)角色:也叫具體目標類,它實現抽象目標中的通知方法,當具體主題的內部狀態發生改變時,通知全部註冊過的觀察者對象。
  3. 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新本身的抽象方法,當接到具體主題的更改通知時被調用。
  4. 具體觀察者(Concrete Observer)角色:實現抽象觀察者中定義的抽象方法,以便在獲得目標的更改通知時更新自身的狀態。

觀察者模式的結構圖以下圖所示:對象

gif

模式的應用實例

利用觀察者模式設計一個程序,分析「人民幣匯率」的升值或貶值對進口公司的進口產品成本或出口公司的出口產品收入以及公司的利潤率的影響。blog

分析:當「人民幣匯率」升值時,進口公司的進口產品成本下降且利潤率提高,出口公司的出口產品收入下降且利潤率下降;當「人民幣匯率」貶值時,進口公司的進口產品成本提高且利潤率下降,出口公司的出口產品收入提高且利潤率提高。接口

這裏的匯率(Rate)類是抽象目標類,它包含了保存觀察者(Company)的 List 和增長/刪除觀察者的方法,以及有關匯率改變的抽象方法 change(int number);而人民幣匯率(RMBrate)類是具體目標, 它實現了父類的 change(int number) 方法,即當人民幣匯率發生改變時經過相關公司;公司(Company)類是抽象觀察者,它定義了一個有關匯率反應的抽象方法 response(int number);進口公司(ImportCompany)類和出口公司(ExportCompany)類是具體觀察者類,它們實現了父類的 response(int number) 方法,即當它們接收到匯率發生改變的通知時做爲相應的反應。rem

下圖所示是其結構圖:產品

gif

程序代碼以下

//測試類
public class RMBrateTest
{
    public static void main(String[] args)
    {
        Rate rate=new RMBrate();         
        Company watcher1=new ImportCompany(); 
        Company watcher2=new ExportCompany();           
        rate.add(watcher1); 
        rate.add(watcher2);           
        rate.change(10);
        rate.change(-9);
    }
}
//抽象目標:匯率
abstract class Rate
{
    protected List<Company> companys=new ArrayList<Company>();   
    //增長觀察者方法
    public void add(Company company)
    {
        companys.add(company);
    }    
    //刪除觀察者方法
    public void remove(Company company)
    {
        companys.remove(company);
    }   
    public abstract void change(int number);
}
//具體目標:人民幣匯率
class RMBrate extends Rate 
{
    public void change(int number)
    {       
        for(Company obs:companys)
        {
            ((Company)obs).response(number);
        }       
    }
}
//抽象觀察者:公司
interface Company
{
    void response(int number);
}
//具體觀察者1:進口公司 
class ImportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民幣匯率升值"+number+"個基點,下降了進口產品成本,提高了進口公司利潤率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民幣匯率貶值"+(-number)+"個基點,提高了進口產品成本,下降了進口公司利潤率。"); 
        }
    } 
} 
//具體觀察者2:出口公司
class ExportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民幣匯率升值"+number+"個基點,下降了出口產品收入,下降了出口公司的銷售利潤率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民幣匯率貶值"+(-number)+"個基點,提高了出口產品收入,提高了出口公司的銷售利潤率。"); 
        }
    } 
}

模式的應用場景

經過前面的分析與應用實例可知觀察者模式適合如下幾種情形。

  1. 對象間存在一對多關係,一個對象的狀態發生改變會影響其餘對象。
  2. 當一個抽象模型有兩個方面,其中一個方面依賴於另外一方面時,可將這兩者封裝在獨立的對象中以使它們能夠各自獨立地改變和複用。
相關文章
相關標籤/搜索