欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#中利用代理實現(xiàn)觀察者設(shè)計模式詳解

 更新時間:2014年01月22日 09:41:57   作者:  
學習模式注重精髓而非模板,本文為了便于說明假定了三方并對三方功能進行了劃分,實際應用并不拘泥于此。如果情況合適將數(shù)據(jù)(文檔)類設(shè)計為單件模式也是一種很不錯的選擇

界面開發(fā)中,經(jīng)常使用觀察者設(shè)計模式來實現(xiàn)文檔/視圖模式,當文檔內(nèi)容改變時,作為觀察者的用戶視圖必須相應作出調(diào)整以向用戶呈現(xiàn)文檔的狀態(tài)。由于語言機制的不同,觀察者設(shè)計模式在不同的語言中實現(xiàn)方法也不盡相同。

在MFC的文檔/視圖模式中,每當文檔內(nèi)容改變都需要調(diào)用UpdateAllView函數(shù)來更新視圖,該函數(shù)會遍歷文檔的每一個視圖,調(diào)用每個視圖的更新函數(shù)來更新視圖,為此文檔須登記每一個使用該文檔的視圖。C#中觀察者設(shè)計模式的實現(xiàn)也可以采用這種方法,但C#提供的代理(delegate)機制為實現(xiàn)觀察者模式提供了更好的方法,該方法和MFC中的方法類似 ,只不過將視圖向文檔注冊這一行為改變?yōu)闉槲臋n類的代理生成實例而已,下面看具體實現(xiàn)方法。

先做如下假定:
1、文檔類為UserData;
2、視圖類為View,實際應用中該View可能是一個Form,也可能是一個UserControl,可能有多個視圖,但每一個和文檔的對應方式都是相同的;
3、主窗體為MainForm;

參與觀察者模式的三方分別為:發(fā)布者(數(shù)據(jù)/文檔類)、訂閱者(視圖類)以及主窗體(MainForm),下面分別介紹各方如何實施以配合觀察者模式的實現(xiàn)!

發(fā)布者:
發(fā)布者的任務是定義數(shù)據(jù)并在數(shù)據(jù)改變時通知訂閱者。通知的實現(xiàn)可以使用普通代理,也可以使用事件,首先在UserData中創(chuàng)建代理和事件,每一個事件在UserData類相應屬性改變時觸發(fā),看下面的代碼:

復制代碼 代碼如下:

  public delegate void UserNameChangedEventHander(object sender, EventArgs e);   //聲明代理
  public event UserNameChangedEventHander NameChanged;   //聲明事件

  private string m_userName;
  public string UserName//定義屬性
  {
get
{
    return m_userName;
}
set
{
    if (m_userName != value)
    {
  m_userName = value;
  NameChanged(this, EventArgs.Empty);    //觸發(fā)事件
    }
}
  }

上述代碼首先聲明了代理,然后聲明了代理對應的事件(事件也算一種特殊的代理),這些代理實例的生成將在視圖中進行,然后在屬性的set函數(shù)中觸發(fā)事件,該事件將在各個訂閱者中得到響應。

訂閱者:
訂閱者的任務是響應發(fā)布者發(fā)布的數(shù)據(jù)改變通知,呈現(xiàn)給用戶實時(相對來說)的系統(tǒng)狀態(tài)。

看下面的代碼:

復制代碼 代碼如下:

 private UserData m_userData = null;   
  public UserData UserDataObj     //定義數(shù)據(jù)(文檔)對象
  {
get
{
    return m_userData;
}
set
{
    m_userData = (UserData)value;     //下面一行添加數(shù)據(jù)對象事件響應函數(shù)
    m_userData.NameChanged += new UserData.UserNameChangedEventHander(UserNameChanged); 
}
  }
  private void UserNameChanged(object sender,EventArgs e)    //定義數(shù)據(jù)對象事件響應函數(shù)
  {
this.tbName.Text = m_userData.UserName;//根據(jù)數(shù)據(jù)對象更新內(nèi)容
this.Invalidate();     //重繪視圖
  }

上述代碼首先在視圖類中定義一數(shù)據(jù)對象屬性,并在屬性的set函數(shù)中添加對數(shù)據(jù)對象所發(fā)布通知的響應。接下來定義了響應數(shù)據(jù)對象通知的函數(shù),在該函數(shù)中更新視圖數(shù)據(jù)并重繪。

主窗體:
主窗體的任務是定義一個相當于全局的數(shù)據(jù)對象,將其賦予每個訂閱該對象的視圖,并在需要的時候改變數(shù)據(jù)對象內(nèi)容。

看下面的代碼:

復制代碼 代碼如下:

 private UserData m_userData;    //發(fā)布者
  private View m_view;//訂閱者

  private void MainForm_Load(object sender, EventArgs e)
  {
m_userData = new UserData(); //生成實例
m_view = new View();
m_view.UserDataObj = m_userData;     //為訂閱者指定發(fā)布者
m_view.Show();     //顯示
m_userData.UserName = "ZPY";    //改變發(fā)布者數(shù)據(jù)  
m_view.TopMost = true;
  } 


在框架窗體類中分別生成發(fā)布者和訂閱者的實例,然后將發(fā)布者實例賦值給訂閱者的數(shù)據(jù)對象屬性,由于C#中類的傳遞默認采用引用傳遞的方式,因此在賦值過程中并不生成臨時對象,MainForm中的m_userData和View中的m_userData所指為同一對象。接下來在主窗體中改變發(fā)布者數(shù)據(jù),通過C#的代理(delegate)機制,訂閱者即能更新自己。

小結(jié)
MFC為開發(fā)者搭好了框架,盡管作了許多的開發(fā),可能很多人還是不太了解什么是所謂的觀察者模式,C#提供了全開放的設(shè)計,可能辛苦些,但不再摸不著頭腦,條理感覺更清晰些,封裝性感覺也比MFC好些!

學習模式注重精髓而非模板,本文為了便于說明假定了三方并對三方功能進行了劃分,實際應用并不拘泥于此。如果情況合適將數(shù)據(jù)(文檔)類設(shè)計為單件模式也是一種很不錯的選擇!總之一句話:掌握精髓,盡情發(fā)揮!

相關(guān)文章

最新評論