欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

設(shè)計(jì)模式之--觀察者模式

系統(tǒng) 1841 0

在日常生活中,有很多需要我們關(guān)注的事務(wù)(比如,股市,樓市等),這些事務(wù)我們可以稱之為主題或者叫信息發(fā)布者,觀察主題的目的是想了解主題的變化(消息)。一種方法當(dāng)然是采用盯人策略,但這種方法有個(gè)固有的缺點(diǎn),就是你盯住主題的時(shí)候,無(wú)法干其他事情,如果需要了解的主題比較多,這種辦法就很麻煩了;另外一種就是主題廣播,我想聽的時(shí)候我就去聽,不想聽的時(shí)候我就不聽,這種方式的好處就是可以使得觀察者不用盯住主題,但缺點(diǎn)是如果信息發(fā)布者的信息發(fā)布是不固定的,觀察者(信息接收者)可能會(huì)漏掉信息。這兩種方式都各有利弊,局域網(wǎng)中的信息傳送采用的其實(shí)就是主題廣播方式,只是接收者也是盯人戰(zhàn)術(shù)。還有一種方式就是信息發(fā)布者提供一個(gè)注冊(cè)機(jī)制,如果你要關(guān)注這個(gè)主題,就可以登記,如果主題有消息時(shí),就按協(xié)定好的方式來(lái)通知注冊(cè)的觀察者。這就是觀察者模式的現(xiàn)實(shí)生活中的原型。

《設(shè)計(jì)模式》中對(duì)觀察模式的定義是:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí), 所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。簡(jiǎn)圖如下: 設(shè)計(jì)模式之--觀察者模式

示例代碼如下:

using System;
using System.Collections;

namespace DesignModelStudy
{
#region 觀察者模式
/* 名稱:Observer 觀察者模式
* 意圖:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí), 所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
* 適用性:
* 當(dāng)一個(gè)抽象模型有兩個(gè)方面, 其中一個(gè)方面依賴于另一方面。將這二者封裝在獨(dú)立的對(duì)象中以使它們可以各自獨(dú)立地改變和復(fù)用。
* 當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象, 而不知道具體有多少對(duì)象有待改變。
* 當(dāng)一個(gè)對(duì)象必須通知其它對(duì)象,而它又不能假定其它對(duì)象是誰(shuí)。換言之, 你不希望這些對(duì)象是緊密耦合的。
*
* 結(jié)構(gòu):
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | Subject | observers | Observer |
* |------------------|--------------------------------→|------------------|
* | Attach(Observer) | | Update() |
* | Detach(Observer) | | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| |__________________|
* | Notify() ○-----|-| for all o in observers{ | |
* |__________________| | o->Update() } | |
* △ |__________________________| |
* | |
* | |
* | △
* | |
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| |
* | ConcreateSubject | subject | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* |------------------------------|←---------------------| ConcreateObserver |
* | GetState() ○------------|-| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄||------------------------| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | SetState() | |return subjectState || Update() ○---------|----| observerState=subject->GetState() |
* |------------------------------| |____________________||------------------------| |______________________________________|
* | subjectState | | observerState |
* |______________________________| |________________________|
*
*
*
*
* */
#endregion
/// <summary>
/// 抽象觀察者,定義了一種主題與具體觀察者之間進(jìn)行通信的標(biāo)準(zhǔn),有兩種含義:1,為主題定義了所能接收其注冊(cè)的觀察者的接口標(biāo)準(zhǔn),
/// 2定義了主題發(fā)布信息時(shí)與觀察者之間通信的接口方法(觀察者提供給主題進(jìn)行傳送消息的方法)。
/// </summary>
public abstract class Observer_Observer
{
public abstract void Update();
}
/// <summary>
/// 抽象主題,主要實(shí)現(xiàn)主題注冊(cè)和通知的機(jī)制(即觀察者模式的基本機(jī)制的實(shí)現(xiàn))
/// 這樣做的好處是只要是繼承自抽象主題的子類都可以應(yīng)用觀察者模式。有利于主題的變化和擴(kuò)展。
/// </summary>
public class Observer_Subject
{
private ArrayList observers = new ArrayList();
//注冊(cè)
public virtual void Attach(Observer_Observer observer)
{
if(observers.IndexOf(observer)<0)
{
observers.Add(observer);
}
}
//取消注冊(cè)
public virtual void Detach(Observer_Observer observer)
{
observers.Remove(observer);
}
//通知
public virtual void Notify()
{
foreach( Observer_Observer o in observers)
{
o.Update();
}
}
}
/// <summary>
/// 具體的主題
/// </summary>
public class Observer_ConcreateSubject : Observer_Subject
{
private string _Name;
private double _Value;
public Observer_ConcreateSubject(string name,double val ) : base()
{
this._Name = name;
this._Value = val;
}
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
public double Value
{
get
{
return _Value;
}
set
{
_Value =value;
}
}
}
/// <summary>
/// 具體觀察者1
/// </summary>
public class Observer_ConcreateObserverA : Observer_Observer
{
private string _Name;
private double _Value;
private Observer_ConcreateSubject subject;
public override void Update()
{
_Name = this.ToString()+"."+subject.Name;
_Value = subject.Value;
System.Windows.Forms.MessageBox.Show(_Name+":"+_Value.ToString());
}
public Observer_ConcreateObserverA(Observer_ConcreateSubject s)
{
this.subject = s;
}
}
/// <summary>
/// 具體觀察者2
/// </summary>
public class Observer_ConcreateObserverB : Observer_Observer
{
private string _Name;
private double _Value;
private Observer_ConcreateSubject subject;
public override void Update()
{
_Name = this.ToString()+"."+subject.Name;
_Value = subject.Value;
System.Windows.Forms.MessageBox.Show(_Name+":"+_Value.ToString());
}
public Observer_ConcreateObserverB(Observer_ConcreateSubject s)
{
this.subject = s;
}
}
public class Observer_Client
{
public static void Test()
{
Observer_ConcreateSubject subject = new Observer_ConcreateSubject("Item",1000);
Observer_Observer o1= new Observer_ConcreateObserverA(subject);
Observer_Observer o2= new Observer_ConcreateObserverB(subject);
subject.Attach(o1);
subject.Attach(o2);
subject.Notify();
}
}
}

考慮到主題的多樣性和觀察者的關(guān)注點(diǎn)和角度的多樣性,上面的觀察者模式具有很大的局限性:

1)抽象主題采用抽象類來(lái)實(shí)現(xiàn),就會(huì)導(dǎo)致一個(gè)主題只能接收一種觀察者,如果主題本身就是有類層次結(jié)構(gòu)的就要求系統(tǒng)必須支持多繼承方式,這顯然是個(gè)很過(guò)分的要求。抽象主題采用接口方式實(shí)現(xiàn)可以解決上述問(wèn)題,這是一種改進(jìn);但又造成一個(gè)問(wèn)題,因?yàn)閺脑O(shè)計(jì)來(lái)講,我們希望對(duì)象的責(zé)任能夠比較單一,如果采用接口實(shí)現(xiàn),那么對(duì)觀察者的注冊(cè)管理就必須由具體主題類來(lái)實(shí)現(xiàn),這顯然增加了主題類的責(zé)任(而且是額外的),一個(gè)解決辦法就是將注冊(cè)管理委托給一個(gè)對(duì)象類來(lái)進(jìn)行,我們可以稱之為注冊(cè)管理對(duì)象,這樣一來(lái)好處有2:一是使得主題的責(zé)任單一,二是解除了主題對(duì)觀察者的依賴,這時(shí)候的多個(gè)主題之間不需要有公共的接口。當(dāng)然,主題需要維護(hù)一個(gè)對(duì)注冊(cè)類的引用,但即使是這樣,好處還是很多,而且可擴(kuò)展性變得更強(qiáng);

2)在實(shí)際應(yīng)用中不同的觀察者對(duì)于關(guān)注的主題和側(cè)重點(diǎn)是不一樣的,觀察者必須知道具提要觀察的主題的結(jié)構(gòu),這就造成了觀察者對(duì)主題的依賴。這種依賴即使觀察者模式的局限,也是觀察者模式在很大程度上無(wú)法避免的情況。

3)增加注冊(cè)管理對(duì)象后,除了分離了一部分主題的責(zé)任,使得主題責(zé)任單一,并對(duì)觀察者解耦外,還有一個(gè)好處就是可以在注冊(cè)對(duì)象增加針對(duì)觀察者的額外功能(比如觀察者計(jì)數(shù)等)。但如果在不需要對(duì)觀察者進(jìn)行管理的情況,無(wú)論是改進(jìn)前的還是改進(jìn)后的觀察者模式都有一個(gè)不利的地方,就是增加了開銷,因?yàn)槎夹枰S護(hù)一個(gè)觀察者對(duì)象池。改進(jìn)的辦法就是利用事件來(lái)實(shí)現(xiàn)。利用事件來(lái)實(shí)現(xiàn)觀察者模式有兩個(gè)好處,一是只要一個(gè)事件類型定義,不需要定義接口和實(shí)現(xiàn)接口,二是不需要維護(hù)觀察者對(duì)象池。如果將主題要發(fā)布的信息參數(shù)化,而且觀察者除了要知道這個(gè)消息,并不需要了解主題的具體細(xì)節(jié)外,還可以解除觀察者與主題之間的耦合關(guān)系。

下面是改進(jìn)后的觀察者模式的實(shí)現(xiàn)示例:

using System;
using System.Collections;
namespace DesignModelStudy
{

//觀察者接口定義
public interface Observer1
{
//被觀察者發(fā)生改變時(shí)會(huì)調(diào)用觀察者的這個(gè)方法。
void Update(object subject);
}
/// <summary>
/// 觀察者聚合集,這樣被觀察者就知道了有那些觀察者在注視它們,以便被觀察者發(fā)生改變時(shí)好通知它們
/// 但這里僅僅是個(gè)接口,具體的管理有實(shí)現(xiàn)類完成。
/// </summary>
public interface Subject1
{
//注冊(cè)觀察者
void AddObserver(Observer1 observer);
//取消注冊(cè)
void RemoveObserver(Observer1 observer);
//實(shí)現(xiàn)該接口以通知所有的觀察者.
void Notify(object realSubject);
}
/// <summary>
/// 具體實(shí)現(xiàn)觀察者管理的具體對(duì)象。
/// </summary>
public class SubjectHelper : Subject1
{
private ArrayList observers = new ArrayList();
public void AddObserver(Observer1 observer)
{
observers.Add(observer);
}
public void RemoveObserver(Observer1 observer)
{
observers.Remove(observer);
}
public void Notify(object realSubject)
{
foreach(Observer1 observer in observers)
{
observer.Update(realSubject);
}
}
}
//注意這里的Album不從Subject或SubjectHelper繼承,顯示了另外一種觀察者模式
//這樣可以使得對(duì)象間的耦合度更小。
//這是被觀察者對(duì)象
public class Album
{
private String name;
//被觀察者要知道觀察者管理對(duì)象,以便通過(guò)這個(gè)類實(shí)現(xiàn)對(duì)觀察者的管理和通知。
private Subject1 playSubject = new SubjectHelper();
public Album(String name)
{ this.name = name; }
public void Play()
{
playSubject.Notify(this);
// code to play the album
}
public String Name
{
get { return name; }
}
public Subject1 PlaySubject
{
get { return playSubject; }
}
}

class Observer1_Client
{
//普通方式
public static void Test()
{
BillingService billing = new BillingService();
CounterService counter = new CounterService();
Album album = new Album("Up");
album.PlaySubject.AddObserver(billing);
album.PlaySubject.AddObserver(counter);
album.Play();
}
//利用事件來(lái)實(shí)現(xiàn)
public static void Test1()
{
BillingService billing = new BillingService();
CounterService counter = new CounterService();
Album_1 album = new Album_1("Up");
album.PlayEvent += new Album_1.PlayHandler(counter.Update);
album.PlayEvent += new Album_1.PlayHandler(billing.Update);
album.Play();
}
}
//具體的觀察者類,每個(gè)觀察者對(duì)被觀察對(duì)象的關(guān)注角度是不同的,下面僅僅列出兩種觀察類
public class CounterService : Observer1
{
public void Update(object subject)
{
if(subject is Album_1)
GenerateCharge((Album_1)subject);
}
private void GenerateCharge(Album_1 album)
{
string name = album.Name;
//code to generate charge for correct album
System.Windows.Forms.MessageBox.Show("Counter:"+name);
}
}
public class BillingService : Observer1
{
public void Update(object subject)
{
if(subject is Album_1)
GenerateCharge((Album_1)subject);
}
private void GenerateCharge(Album_1 album)
{
string name = album.Name;
//code to generate charge for correct album
System.Windows.Forms.MessageBox.Show("Billing:"+name);
}
}
//事件方式實(shí)現(xiàn).
public class Album_1
{
private String name;
public delegate void PlayHandler(object sender);
public event PlayHandler PlayEvent;
public Album_1(String name)
{ this.name = name; }
public void Play()
{
Notify();
// code to play the album
}
private void Notify()
{
if (PlayEvent != null)
PlayEvent(this);
}
public String Name
{
get { return name; }
}
}
}
后記:

上面的討論基本都局限于觀察者與主題之間的組織,沒(méi)有討論觀察者和主題之間的通信(上面的模式基本都采用調(diào)用通信),實(shí)際上主題和觀察者之間的通信方式很多,但這與具體的操作系統(tǒng)和網(wǎng)絡(luò)有關(guān)。在通信方式可以支持的情況下,不僅可以實(shí)現(xiàn)消除觀察者和主題之間的耦合關(guān)系,還可以讓觀察者和主題位于不同的地址空間。

典型應(yīng)用:MVC模式,Delphi的數(shù)據(jù)感知控件和數(shù)據(jù)集,C#的控件和綁定數(shù)據(jù)源等。

設(shè)計(jì)模式之--觀察者模式


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 91看片免费版 | 亚洲第一成年免费网站 | 天天做天天添婷婷我也去 | 国产美女视频网站 | 久草久视频 | 久久精品免费观看 | 亚洲免费在线视频 | 好看的中文字幕在线 | 91精品亚洲| 日本娇小videos高潮 | 亚洲呦呦系列视频 | 亚洲欧美视频一区二区 | 色综合天天综合网看在线影院 | 伊人无码高清 | 国产日产在线观看 | 日韩在线观看中文 | 久久精品人人做人人看最新章 | 成人黄色免费网站 | 一级黄色片视频 | 日本欧美一区二区三区不卡视频 | 国产黄色一级毛片 | 韩漫重考生漫画画免费读漫画下拉式土豪漫 | 在线观看国产日韩欧美 | 午夜理论电影在线观看亚洲 | 性xxxx视频播放免费 | www.82gan.com | 久久人人精品 | 日本在线网站 | 91成人影院未满十八勿入 | 91在线播放视频 | 操操日 | 日韩一级片在线观看 | 国产精品欧美一区二区在线看 | 日本精品视频 | 国产精品福利在线 | 欧美日韩免费播放一区二区 | 亚洲人成网站看在线播放 | 日本肥老太成熟 | 国产无遮挡裸体免费视频 | 欧美成人黑人视频免费观看 | 先锋资源久久 |