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

C#設(shè)計(jì)模式之觀察者模式實(shí)例講解

 更新時(shí)間:2014年10月25日 09:43:26   投稿:junjie  
這篇文章主要介紹了C#設(shè)計(jì)模式之觀察者模式實(shí)例講解,本文詳細(xì)講解了觀察者模式的定義、優(yōu)缺點(diǎn)、代碼實(shí)例等,需要的朋友可以參考下

前言

最近開始花點(diǎn)心思研究下設(shè)計(jì)模式,主要還是讓自己寫的代碼可重用性高、保證代碼可靠性。所謂設(shè)計(jì)模式,我找了下定義:是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。毫無疑問,設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的;設(shè)計(jì)模式使代碼編制真正工程化;設(shè)計(jì)模式是軟件工程的基石脈絡(luò),如同大廈的結(jié)構(gòu)一樣。

為什么要提倡“Design Pattern(設(shè)計(jì)模式)”?

根本原因是為了代碼復(fù)用,增加可維護(hù)性。因此這次我們來學(xué)習(xí)下設(shè)計(jì)模式,最后會(huì)通過C#語言來實(shí)現(xiàn)這些設(shè)計(jì)模式作為例子,深刻理解其中的精髓。

定義

觀察者模式,有時(shí)被稱作發(fā)布/訂閱模式,觀察者模式定義了一種一對多的依賴關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象。這個(gè)主題對象在狀態(tài)發(fā)生變化時(shí),會(huì)通知所有觀察者對象,使它們能夠自動(dòng)更新自己。

特點(diǎn)

模式中具有的角色

1。 抽象主題(Subject):它把所有觀察者對象的引用保存到一個(gè)聚集里,每個(gè)主題都可以有任何數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除觀察者對象。

2。 具體主題(ConcreteSubject):將有關(guān)狀態(tài)存入具體觀察者對象;在具體主題內(nèi)部狀態(tài)改變時(shí),給所有登記過的觀察者發(fā)出通知。

3。抽象觀察者(Observer):為所有的具體觀察者定義一個(gè)接口,在得到主題通知時(shí)更新自己。

4。具體觀察者(ConcreteObserver):實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調(diào)。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

一、通知通信

觀察者模式支持廣播通信。被觀察者會(huì)向所有的注冊過的觀察者發(fā)出通知。

二、聚耦合

觀察者模式在被觀察者和觀察者之間建立了一個(gè)抽象的耦合,被觀察者并不知道任何一個(gè)具體的觀察者,只是保存著抽象觀察者的列表,每個(gè)具體觀察者都符合一個(gè)抽象觀察者的接口。

缺點(diǎn):

一、時(shí)間復(fù)雜度

如果一個(gè)被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。

二、內(nèi)聯(lián)不足

雖然觀察者模式可以隨時(shí)使觀察者知道所觀察的對象發(fā)送了變化,但是觀察者模式?jīng)]有相應(yīng)的機(jī)制使觀察者知道所觀察的對象是怎樣發(fā)生變化的。

三、容易出現(xiàn)循環(huán)調(diào)用

如果在被觀察者之間有循環(huán)依賴的話,被觀察者會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,導(dǎo)致系統(tǒng)崩潰,在使用觀察者模式應(yīng)特別注意這點(diǎn)。

實(shí)現(xiàn)思路

下面以xmfdsh發(fā)布一篇博客的例子來說明觀察者模式的實(shí)現(xiàn)。關(guān)注了xmfdsh的朋友們,便可以通過觀察者模式來實(shí)時(shí)得到博客進(jìn)行了更新的信息。當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面,將這兩者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立地改變和復(fù)用的情況下。從方面的這個(gè)詞中可以想到,觀察者模式肯定在AOP(面向方面編程)中有所體現(xiàn)。因此這種需求使用觀察者模式來解決就再恰當(dāng)不過了。

觀察者向目標(biāo)“訂閱”它的改變,而目標(biāo)發(fā)生改變后就“通知”所有已經(jīng)“訂閱”了它的改變的觀察者,從而執(zhí)行“訂閱”的內(nèi)容。這種機(jī)制的好處在于降低耦合度,分工明確,目標(biāo)只負(fù)責(zé)在自身狀態(tài)發(fā)生改變或做出某種行為時(shí)向自身的訂閱清單發(fā)出“通知”,而不是直接調(diào)用觀察者的行為(方法);觀察者只負(fù)責(zé)向目標(biāo)“訂閱”它的變化,以及定義自身在收到目標(biāo)“通知”后所需要做出的具體行為(也就是訂閱的內(nèi)容)

復(fù)制代碼 代碼如下:

// 訂閱號抽象類
    public abstract class Blog
    {
        // 保存訂閱者列表
        private List<IObserver> observers = new List<IObserver>();

        public string Symbol { get; set; }//描寫訂閱號的相關(guān)信息
        public string Info { get; set; }//描寫此次update的信息
        public Blog(string symbol, string info)
        {
            this.Symbol = symbol;
            this.Info = info;
        }

        // 對同一個(gè)訂閱號,新增和刪除訂閱者的操作
        public void AddObserver(IObserver ob)
        {
            observers.Add(ob);
        }
        public void RemoveObserver(IObserver ob)
        {
            observers.Remove(ob);
        }

        public void Update()
        {
            // 遍歷訂閱者列表進(jìn)行通知
            foreach (IObserver ob in observers)
            {
                if (ob != null)
                {
                    ob.Receive(this);
                }
            }
        }
    }

    // 具體訂閱號類
    public class MyBlog : Blog
    {
        public MyBlog(string symbol, string info)
            : base(symbol, info)
        {
        }
    }

    // 訂閱者接口
    public interface IObserver
    {
        void Receive(Blog tenxun);
    }

    // 具體的訂閱者類
    public class Subscriber : IObserver
    {
        public string Name { get; set; }
        public Subscriber(string name)
        {
            this.Name = name;
        }

        public void Receive(Blog xmfdsh)
        {
            Console.WriteLine("訂閱者 {0} 觀察到了{(lán)1}{2}", Name, xmfdsh.Symbol, xmfdsh.Info);
        }
    }

    // 客戶端測試
    class Program
    {
        static void Main(string[] args)
        {
            Blog xmfdsh = new MyBlog("xmfdsh", "發(fā)布了一篇新博客");

            // 添加訂閱者
            xmfdsh.AddObserver(new Subscriber("王尼瑪"));
            xmfdsh.AddObserver(new Subscriber("唐馬儒"));
            xmfdsh.AddObserver(new Subscriber("王蜜桃"));
            xmfdsh.AddObserver(new Subscriber("敖尼瑪"));

            //更新信息
            xmfdsh.Update();
            //輸出結(jié)果,此時(shí)所有的訂閱者都已經(jīng)得到博客的新消息
            Console.ReadLine();
        }
    }

運(yùn)行的效果圖如下:

此類實(shí)現(xiàn)方法的類圖如下:

這個(gè)類圖是visual studio生成的,可能看起來比較混亂把,這樣的實(shí)現(xiàn)就是觀察者模式的實(shí)現(xiàn)。任何時(shí)候,只要執(zhí)行了Update方法,便會(huì)自動(dòng)的去通知推送給訂閱了此訂閱號 的用戶,然而在C#中,我們更多的是使用委托與事件來簡化觀察者模式的實(shí)現(xiàn)。

復(fù)制代碼 代碼如下:

class Program
    {
        // 委托充當(dāng)訂閱者接口類
        public delegate void NotifyEventHandler(object sender);

        // 抽象訂閱號類
        public class Blog
        {
            public NotifyEventHandler NotifyEvent;
            public string Symbol { get; set; }//描寫訂閱號的相關(guān)信息
            public string Info { get; set; }//描寫此次update的信息
            public Blog(string symbol, string info)
            {
                this.Symbol = symbol;
                this.Info = info;
            }

            #region 新增對訂閱號列表的維護(hù)操作
            public void AddObserver(NotifyEventHandler ob)
            {
                NotifyEvent += ob;
            }
            public void RemoveObserver(NotifyEventHandler ob)
            {
                NotifyEvent -= ob;
            }

            #endregion

            public void Update()
            {
                if (NotifyEvent != null)
                {
                    NotifyEvent(this);
                }
            }
        }

        // 具體訂閱號類
        public class MyBlog : Blog
        {
            public MyBlog(string symbol, string info)
                : base(symbol, info)
            {
            }
        }

        // 具體訂閱者類
        public class Subscriber
        {
            public string Name { get; set; }
            public Subscriber(string name)
            {
                this.Name = name;
            }

            public void Receive(Object obj)
            {
                Blog xmfdsh = obj as Blog;

                if (xmfdsh != null)
                {
                    Console.WriteLine("訂閱者 {0} 觀察到了{(lán)1}{2}", Name, xmfdsh.Symbol, xmfdsh.Info);
                }
            }
        }

        static void Main1(string[] args)
        {
            Blog xmfdsh = new MyBlog("xmfdsh", "發(fā)布了一篇新博客");
            Subscriber wnm = new Subscriber("王尼瑪");
            Subscriber tmr = new Subscriber("唐馬儒");
            Subscriber wmt = new Subscriber("王蜜桃");
            Subscriber anm = new Subscriber("敖尼瑪");

            // 添加訂閱者
            xmfdsh.AddObserver(new NotifyEventHandler(wnm.Receive));
            xmfdsh.AddObserver(new NotifyEventHandler(tmr.Receive));
            xmfdsh.AddObserver(new NotifyEventHandler(wmt.Receive));
            xmfdsh.AddObserver(new NotifyEventHandler(anm.Receive));

            xmfdsh.Update();

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();

            Console.WriteLine("移除訂閱者王尼瑪");
            xmfdsh.RemoveObserver(new NotifyEventHandler(wnm.Receive));
            xmfdsh.Update();

            Console.ReadLine();
        }
    }

運(yùn)行的結(jié)果:

類圖:

總結(jié)

到這里,觀察者模式就講完了,觀察者模式定義了一種一對多的依賴關(guān)系,讓多個(gè)觀察者對象可以同時(shí)監(jiān)聽某一個(gè)主題對象,這個(gè)主題對象在發(fā)生狀態(tài)變化時(shí),會(huì)通知所有觀察者對象,使它們能夠自動(dòng)更新自己,因此在一些需求上是當(dāng)一個(gè)對象的改變需要同時(shí)改變多個(gè)其他對象的時(shí)候,且不知道多少個(gè)對象需要去通知改變的時(shí)候,觀察者模式就成了首選,這種模式的用的最多的,在我的開發(fā)經(jīng)歷中便是windows phone手機(jī)客戶端的開發(fā)了,經(jīng)常要用到這類的委托事件的處理,用多了后發(fā)現(xiàn)就習(xí)以為常,這種模式也就沒那么稀奇了。

源碼下載地址:http://xiazai.jb51.net/201410/tools/ConsoleApplication2.rar

相關(guān)文章

  • C#窗體通訊錄系統(tǒng)的示例代碼

    C#窗體通訊錄系統(tǒng)的示例代碼

    本文主要介紹了C#窗體通訊錄系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 深入理解C#的數(shù)組

    深入理解C#的數(shù)組

    本篇文章主要介紹了C#的數(shù)組,數(shù)組是一種數(shù)據(jù)結(jié)構(gòu),詳細(xì)的介紹了數(shù)組的聲明和訪問等,有興趣的可以了解一下。
    2016-11-11
  • C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle

    C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle

    這篇文章主要介紹了C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-02-02
  • C#并發(fā)實(shí)戰(zhàn)記錄之Parallel.ForEach使用

    C#并發(fā)實(shí)戰(zhàn)記錄之Parallel.ForEach使用

    這篇文章主要給大家介紹了關(guān)于C#并發(fā)實(shí)戰(zhàn)記錄之Parallel.ForEach使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 深入分析C#中的異步和多線程

    深入分析C#中的異步和多線程

    這篇文章主要介紹了C#中異步和多線程的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下
    2021-01-01
  • Unity3D開發(fā)之獲取所有的子對象的方法詳解

    Unity3D開發(fā)之獲取所有的子對象的方法詳解

    這篇文章主要為大家詳細(xì)介紹了三種Unity3D中獲取所有的子對象(child)的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • C# dataset存放多張表的實(shí)例

    C# dataset存放多張表的實(shí)例

    這篇文章主要介紹了C# dataset存放多張表的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Unity Shader實(shí)現(xiàn)水波紋效果

    Unity Shader實(shí)現(xiàn)水波紋效果

    這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)水波紋效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C#異步執(zhí)行任務(wù)的方法

    C#異步執(zhí)行任務(wù)的方法

    這篇文章主要介紹了C#異步執(zhí)行任務(wù)的方法,以一個(gè)簡單實(shí)例形式分析了C#異步執(zhí)行的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 輕松學(xué)習(xí)C#的抽象類

    輕松學(xué)習(xí)C#的抽象類

    輕松學(xué)習(xí)C#的抽象類,對C#的抽象類感興趣的朋友可以參考本篇文章,幫助大家更靈活的運(yùn)用C#的抽象類
    2015-11-11

最新評論