一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C# - C# 觀察者模式實(shí)例介紹

C# 觀察者模式實(shí)例介紹

2021-04-14 14:44C#教程網(wǎng) C#

觀察者模式:定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主體對(duì)象,這個(gè)主題對(duì)象在狀態(tài)發(fā)生變化時(shí),會(huì)通知所有觀察者。當(dāng)一個(gè)對(duì)象改變需要同時(shí)改變其他對(duì)象,而且他不知道具體有多少對(duì)象需要改變的時(shí)

觀察者模式

觀察者模式:定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主體對(duì)象,這個(gè)主題對(duì)象在狀態(tài)發(fā)生變化時(shí),會(huì)通知所有觀察者。當(dāng)一個(gè)對(duì)象改變需要同時(shí)改變其他對(duì)象,而且他不知道具體有多少對(duì)象需要改變的時(shí)候,應(yīng)該考慮使用觀察者模式。

觀察者結(jié)構(gòu)圖:
C# 觀察者模式實(shí)例介紹

使用場(chǎng)景:老板回來通知員工需要進(jìn)入工作狀態(tài)。
定義觀察者的抽象類:

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


abstract class Observer
{
protected string name;
protected ISubject sub;
public Observer(string name, ISubject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}


看NBA直播的同事:

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


//使用OO
class NBAObserver : Observer
{
public NBAObserver(string name, ISubject sub)
: base(name, sub)
{ }
public override void Update()
{
//throw new NotImplementedException();
Console.WriteLine("{0} {1}關(guān)閉NBA直播,繼續(xù)工作!",sub.SubjectState,name);
}
}
//使用事件和委托
class NBAObserver2
{
private string name;
private ISubject2 sub;
public NBAObserver2(string name, ISubject2 sub)
{
this.name = name;
this.sub = sub;
}
public void CloseStockMarket()
{
Console.WriteLine("{0} {1}關(guān)閉NBA直播,繼續(xù)工作!", sub.SubjectState, name);
}
}


看股票的同事:

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


//使用OO
class StockObserver : Observer
{
public StockObserver(string name, ISubject sub) : base(name,sub)
{ }
public override void Update()
{
//throw new NotImplementedException();
Console.WriteLine("{0} {1}關(guān)閉股票行情,繼續(xù)工作!",sub.SubjectState,name);
}
}
//使用事件和委托
class StockObserver2
{
private string name;
private ISubject2 sub;
public StockObserver2(string name, ISubject2 sub)
{
this.name = name;
this.sub = sub;
}
public void CloseNBA()
{
Console.WriteLine("{0} {1}關(guān)閉股票行情,繼續(xù)工作!", sub.SubjectState, name);
}
}


上的身份是訂閱者,下面定義發(fā)布者:

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


//使用OO
interface ISubject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState
{
get;
set;
}
}
class Boss : ISubject
{
private IList<Observer> observers = new List<Observer>();
private string action;
public void Attach(Observer observer)
{
observers.Add(observer);
}
public void Detach(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer o in observers)
{
o.Update();
}
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
//使用事件和委托
interface ISubject2
{
void Notify();
string SubjectState
{
get;
set;
}
}
delegate void EventHandler();
class Boss2 : ISubject2
{
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}


主函數(shù)調(diào)用:

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


class Program
{
static void Main(string[] args)
{
//觀察者模式OO實(shí)現(xiàn)
Boss huhansan = new Boss();
StockObserver tongshi1 = new StockObserver("name1",huhansan);
NBAObserver tonshi2 = new NBAObserver("name2", huhansan);
huhansan.Attach(tongshi1);
huhansan.Attach(tonshi2);
huhansan.SubjectState = "我1回來了";
huhansan.Notify();
//觀察者模式c#事件實(shí)現(xiàn)
Boss2 huhansan2 = new Boss2();
StockObserver2 tongshi3 = new StockObserver2("name3", huhansan2);
NBAObserver2 tonshi4 = new NBAObserver2("name4", huhansan2);
huhansan2.Update += new EventHandler(tongshi3.CloseNBA);
huhansan2.Update += new EventHandler(tonshi4.CloseStockMarket);
huhansan2.SubjectState = "我2回來了";
huhansan2.Notify();
Console.ReadKey();
}
}


委托就是一種引用方法的類型,一旦為委托分配了方法,委托將與該方法具有完全相同的行為。委托方法的使用可以像其他任何方法一樣,具有參數(shù)和返回值。委托可以看做是對(duì)函數(shù)的抽象,是函數(shù)的一個(gè)類,委托實(shí)例代表一個(gè)具體的函數(shù),而且一個(gè)委托可以搭載多個(gè)方法,所有方法被依次喚醒。

1 觀察者模式
一個(gè)簡(jiǎn)單的例子,比如說貓叫,老鼠跑,主人被驚醒。
在不知道觀察者模式之前,我們的代碼可能是這樣的。

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


//老鼠類  
class Mouse   
{  
     public void Run()   
     {  
         Console.WriteLine("老鼠跑了!");  
     }  
}  
//主人類  
class Master   
{  
     public void Wake()  
     {  
         Console.WriteLine("主人醒了!");  
     }  
}  
//貓類  
class Cat   
{  
     public void Cry ()  
     {  
         Console.WriteLine("貓叫了!");  
         new Mouse().Run();//貓叫的同時(shí),調(diào)用老鼠跑的方法。  
         new Master().Wake();//貓叫的同時(shí),調(diào)用主人醒的方法。  
     }  
}  
class Program  
{  
     static void Main(string[] args)  
     {  
         Cat cat = new Cat();  
         cat.Cry();  
         Console.ReadLine();  
     }  
}  


這個(gè)代碼基本上能實(shí)現(xiàn)所有的功能。但是,這個(gè)方法特別不利用擴(kuò)展,
試想,如果,貓叫后,狗也叫,那是不是也要在貓叫的方法里重新加入狗叫的方法?
或者說,貓叫后,主人他老婆也醒了,是不是也要在貓叫的方法里加入他老婆醒的方法呢?
顯然,這樣的代碼不利用維護(hù),也不是面向?qū)ο蟮拇a。
觀察者模式能夠很好的解決這個(gè)問題。
觀察者模式定義對(duì)象間的一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于他的對(duì)象都得到通知并自動(dòng)更新。在我們的例子中,貓和老鼠,主人,狗,主人他老婆是一對(duì)多的依賴,當(dāng)貓叫時(shí),所有依賴于它的對(duì)象都會(huì)自動(dòng)執(zhí)行某個(gè)操作。
觀察者模式的實(shí)現(xiàn),一般有下面四部分組成。
1.ISubject接口(抽象目標(biāo)),含方法Notify,Register,UnRegister(名字可以自己任意取名)
2.Subject類(實(shí)體目標(biāo)),實(shí)現(xiàn)ISubject接口,一般只有一個(gè)
3.IObservable接口(抽象觀察者)。
4 Observer類(實(shí)體觀察者),實(shí)現(xiàn)IObservable接口,一般有多個(gè)。
觀察者模式中的“注冊(cè)--通知--注銷”圖示:
1. 觀察者(Observer)將自己(Regiester)注冊(cè)到被觀察對(duì)象(Subject)中,被觀察對(duì)象將觀察者放在一個(gè)容器(Container)。Container一般為Ilist,Arraylist等數(shù)據(jù)結(jié)構(gòu),存放多個(gè)IObservable接口變量。
2.當(dāng)被觀察對(duì)象(Subject)發(fā)生變化(如圖中的AskPriceChanged)時(shí),容器(Container)中的所有觀察者(Observer)都得到通知(Notify 方法),此時(shí)觀察者會(huì)自動(dòng)執(zhí)行某些方法。
3.當(dāng)觀察者不想繼續(xù)觀察被觀察者時(shí),可以注銷(UnRegiester方法)
上面的例子中改造后變成:
1.ISubject接口:

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


interface ISubject  
    {  
        void Notify();//主題變動(dòng)時(shí),通知雖有觀察者  
        void Regiester(IObservable o);//觀察者注冊(cè)  
        void UnRegiester(IObservable o);//觀察者取消注冊(cè),此時(shí)主題發(fā)生任何變動(dòng),觀察者都不會(huì)得到通知。  
    }


2.Subject 類:

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


class Cat : ISubject  
   {  
       private IList<IObservable> observers = new List<IObservable>();  
       public void Notify()  
       {  
           foreach (IObservable o in observers) //逐個(gè)通知觀察者  
           {  
               o.Action();  
           }  
       }  
       public void Regiester(IObservable o)  
       {  
           if (o != null || !observers.Contains(o))  
           {  
               observers.Add(o);  
           }  
       }  
       public void UnRegiester(IObservable o)  
       {  
           if (observers != null && observers.Contains(o))  
           {  
               observers.Remove(o);  
           }  
       }  
       public void Cry()  
       {  
           Console.WriteLine("貓叫了!");  
           Notify();  
       }  
   }


3. IObservable 接口:

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


interface IObservable  
{  
    void Action();//觀察者對(duì)主題變動(dòng)所對(duì)應(yīng)的操作  
}


4.Observer類(2個(gè),Mouse和Master)

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


class Mouse : IObservable  
   {  
       public void Action()  
       {  
           Console.WriteLine("鼠跑了!");  
       }  
   }  
   class Master : IObservable  
   {  
       public void Action()  
       {  
           Console.WriteLine("主人醒了!");  
       }  
   }


5.主程序

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


Mouse mouse = new Mouse();  
           Master master = new Master();  
           Cat cat = new Cat();  
           cat.Regiester(mouse);  
           cat.Regiester(master);  
           cat.Cry();  
           Console.ReadLine();


這樣就實(shí)現(xiàn)了觀察者模式,通過把依賴類注冊(cè)到主體類中,當(dāng)主體類發(fā)生變化時(shí),所有依賴類都得到了通知。如果需要擴(kuò)展,比如說象上面例子的狗也叫了,我們可以定義一個(gè)狗類,然后在主程序中把狗對(duì)象注冊(cè)到貓類中就可以了。如果不想依賴于貓類,也可以通過UnRegiester方法取消綁定。
同時(shí),這也符合設(shè)計(jì)中的高內(nèi)聚,低耦合的原則。

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


using System;
using System.Collections.Generic;
using System.Text;
namespace Sample
{
    public delegate void CatCallEventHandler();
    class Program
    {
        static void Main(string[] args)
        {
            Cat cat = new Cat();
            Mouse mouse = new Mouse(cat);
            Master master = new Master(mouse);
            cat.Call();
        }
    }
    class Cat
    {
        public event CatCallEventHandler catevent;
        public void Call()
        {
            Console.WriteLine("喵喵.....");
            catevent();
        }
    }
    class Mouse
    {
        public event CatCallEventHandler mouseevent;
        public Mouse(Cat cat)
        {
            cat.catevent += new CatCallEventHandler(this.MouseRun);
        }
        public void MouseRun()
        {
            Console.WriteLine("老鼠跑");
            mouseevent();
        }
    }
    class Master
    {
        public Master(Mouse mouse)
        {
            mouse.mouseevent+=new CatCallEventHandler(this.JingXing);
        }
        public void JingXing()
        {
            Console.WriteLine("主人被驚醒");
        }
    }
}

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成年人免费观看视频网站 | 问一问免费咨询 | 爽爽窝窝午夜精品一区二区 | 精品免费视频 | 91小视频在线观看免费版高清 | 免费一级日本c片完整版 | 火影忍者羞羞 | 国产成年人视频 | 免费99精品国产自在现线 | 欧美灰丝袜丝交nylons | 精品无码久久久久久久久 | 99福利影院 | 久久中文字幕无线观看 | yellow片在线观看 | 91chinese 永久免费 | 国产精品一级片 | 精品国产免费久久久久久 | 含羞草传媒网站免费进入欢迎 | 精品国产91高清在线观看 | 亚洲国产精品一区二区久久 | 国产香蕉97碰碰在线视频 | 国产成人精品一区二三区2022 | 亚洲成人77777 | 日韩中文字幕一区 | 国产日韩精品一区二区在线观看 | 日韩版码免费福利视频 | 欧美kkk4444在线观看 | 日韩国产欧美成人一区二区影院 | 91精品啪在线观看国产老湿机 | 日本免费一区二区三区a区 日本免费三片在线观看 | 国产日韩一区二区三区 | 亚洲免费二区 | 四虎最新紧急更新地址 | 久久久久久久国产精品视频 | 青青青在线视频 | 欧美帅老头oldmangay | 二次元美女挤奶漫画 | 欧美日韩亚洲另类人人澡 | 女人肮脏的交易中文字幕未删减版 | 色老板成人永久免费视频 | 5x社区发源地最新地址 |