面向對象編程思想-觀察者模式

一、引言

相信猿友都大大小小經歷過一些面試,其中有道經典題目,場景是貓咪叫了一聲,老鼠跑了,主人被驚醒(設計有擴展性的可加分)。對于初學者來說,可能一臉懵逼,這啥跟啥啊是,其實博主當年也這感覺,O(∩_∩)O哈哈~好了,廢話不多說,今天我們要學習的內容就是要解決這種業務場景——觀察者模式,又叫發布-訂閱(Publish/Subscrible)模式

二、觀察者模式

定義:觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象狀態發生變化時,會通知所有觀察者對象,使它們能夠自行更新自己

下面是觀察者模式結構圖:

                          該圖示出自“大話設計模式”


下面通過大家都熟悉的生活場景來幫助我們一步步了解觀察者模式

場景:上自習課的時候,困了想睡覺,通常是會跟同桌說:“老師來了叫我下,我睡會”。(大多數人都是這樣吧,嘿嘿)

下面是代碼demo:

    //主題類class ConcreteSubject{private IList<ConcreteObserver> lstConcreteObserver = new List<ConcreteObserver>();private string action;//添加觀察者public void Add(ConcreteObserver concreteObserver){lstConcreteObserver.Add(concreteObserver);}//移除觀察者public void Remove(ConcreteObserver concreteObserver){lstConcreteObserver.Remove(concreteObserver);}//通知觀察者類public void Notify(){foreach (ConcreteObserver observer in lstConcreteObserver){observer.Update();}}//定義主題發現的某一狀態public string ConcreteAction{get { return action; }set { action = value; }}}//觀察者類class ConcreteObserver{protected ConcreteSubject subject;protected string name;public ConcreteObserver(ConcreteSubject subject, string name){this.subject = subject;this.name = name;}//觀察者更新行為public void Update(){Console.WriteLine($"{subject.ConcreteAction},{name},別睡覺了,快醒醒!");}}static void Main(string[] args){ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observer = new ConcreteObserver(subject, "michael");subject.Add(observer);subject.ConcreteAction = "老師來了";subject.Notify();Console.Read();}
View Code

分析:乍一看是寫的不錯,實現了老師來時同桌通知michael,但是仔細想一下,假如現在情況變了,同桌另一邊的同學在打游戲,也讓老師來時通知一下,怎么辦?這時我們就需要去修改ConcreteSubject類中對觀察者ConcreteObserver的引用,還有另外一種情況,假如某天同桌請假了,通常會讓前后排的同學通知觀察者,即修改觀察者類ConcreteObserver中對ConcreteSubject的引用。這種相互耦合的設計顯然是不太好,當場景變了的時候,不得不去修改原有代碼,違背了開放-封閉原則。

下面看一下大話設計模式中的例子是如何介紹觀察者模式的:

     //抽象觀察者類abstract class Observer{public abstract void Update();}//抽象主題類abstract class Subject{private IList<Observer> lstConcreteObserver = new List<Observer>();public void Add(Observer concreteObserver){lstConcreteObserver.Add(concreteObserver);}public void Remove(Observer concreteObserver){lstConcreteObserver.Remove(concreteObserver);}public void Notify(){foreach (Observer observer in lstConcreteObserver){observer.Update();}}}//具體觀察者類class ConcreteObserver:Observer{protected ConcreteSubject subject;protected string name;private string observerState;public ConcreteObserver(ConcreteSubject subject, string name){this.subject = subject;this.name = name;}public override void Update(){this.observerState = subject.ConcreteAction;Console.WriteLine($"the observer's of {name} state is {observerState}");}}//具體主題對象class ConcreteSubject:Subject{      private string action;      public string ConcreteAction{get { return action; }set { action = value; }}}static void Main(string[] args){ConcreteSubject subject = new ConcreteSubject();subject.Add(new ConcreteObserver(subject, "michael"));subject.Add(new ConcreteObserver(subject, "jarle"));subject.Add(new ConcreteObserver(subject, "cumming"));subject.ConcreteAction = "Ready";subject.Notify();Console.Read();}
View Code

?分析:這次是不是可擴展性更高了?嗯,是的。觀察者與主題對象都依賴于抽象,而不依賴與具體,使得各自變化都不會影響到另一邊

其實現在已經很好了,但是這樣具體的觀察者都要依賴于觀察者的抽象,那能不能再進行優化一次呢?答案是完全可以的。

下面我們用委托事件來解決開頭那個考爛了的面試題,解釋如何優化的

委托:是一種引用類型,表示對具有特定參數列表和返回類型的方法的引用

    class Mao{private string name;public delegate void MaoDelegateHandler();public event MaoDelegateHandler MaoEventHandler;public Mao(string name){this.name = name;}public void Miao(){Console.WriteLine($"{this.name}叫了一聲");Notify();}public void Notify(){if (MaoEventHandler != null)MaoEventHandler();}public string Name{get { return name; }set { name = value; }}}class Laoshu{public void Run(){Console.WriteLine("老鼠逃跑了");}}class People{public void Wake(){Console.WriteLine("主人被驚醒了");}}class Program{static void Main(string[] args){Mao mao = new Mao("大臉貓");Laoshu laoshu = new Laoshu();People people = new People();//注冊事件 這兩種方式都可以mao.MaoEventHandler += new Mao.MaoDelegateHandler(laoshu.Run);mao.MaoEventHandler += people.Wake;//貓叫了一聲 會自動調用注冊過的方法
            mao.Miao();Console.Read();}}
View Code

分析:用委托事件來實現,發布者和訂閱者之間沒有耦合,是不是有優化了一步呢?O(∩_∩)O~

優點:

1.觀察者模式解除了發布者和訂閱者的耦合,兩者都依賴于抽象,而不是具體的,使得兩者可以各自獨立的變化

缺點:

1.觀察者對象如果很多的話,被觀察者通知會耗時增多

2.在被觀察者之間如果有相互依賴的話,會相互調用,導致系統崩潰(小白注意)

適用場景:

1.當一個對象改變需要改變其它對象時,而且不知道有多少個對象需要改變

2.當一個抽象模型有兩個方面,一個方面依賴于另一個方面,將兩者封裝在獨立的對象中以使它們可以各自獨立的變化和復用

?

介紹到這里其實觀察這模式已經結束了,但是我覺得很多小白搞不懂winform開發程序中的grid單擊、雙擊等事件,方法后面的參數sender和e分別是什么。。。下面再簡要分析一下

    class Mao{private string name;//聲明委托public delegate void MaoDelegateHandler(object sender, MaoEventArgs e);//聲明事件public event MaoDelegateHandler MaoEventHandler;public class MaoEventArgs : EventArgs{private string name;public MaoEventArgs(string name){this.name = name;}}public Mao(string name){this.name = name;}//發布者 某一行為后 發出通知public void Miao(){Console.WriteLine($"{this.name}叫了一聲");//建立MaoEventArgs對象MaoEventArgs e = new MaoEventArgs(this.Name);//調用通知方法
            Notify(e);}public void Notify(MaoEventArgs e){//如果有訂閱者注冊if (MaoEventHandler != null)//執行所有注冊的方法MaoEventHandler(this,e);}public string Name{get { return name; }set { name = value; }}}class Laoshu{//是不是很熟悉,請自行腦補winfom中grid的事件及sender和e是什么public void Run(object sender,Mao.MaoEventArgs e){Mao mao = (sender as Mao);Console.WriteLine($"{mao.Name}來了,老鼠逃跑了");}}class People{public void Wake(object sender, Mao.MaoEventArgs e){Mao mao = (sender as Mao);Console.WriteLine($"{mao.Name}的主人被驚醒了");}}class Program{static void Main(string[] args){Mao mao = new Mao("大臉貓");Laoshu laoshu = new Laoshu();People people = new People();//注冊事件 這兩種方式都可以mao.MaoEventHandler += new Mao.MaoDelegateHandler(laoshu.Run);mao.MaoEventHandler += people.Wake;//貓叫了一聲 會自動調用注冊過的方法
            mao.Miao();Console.Read();}}
View Code

分析:ok,這下面試的時候再也不怕面試官問你觀察者模式相關知識了吧。。。

?

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

轉載于:https://www.cnblogs.com/jdzhang/p/7397544.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391614.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391614.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391614.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

typescript 使用_如何使用TypeScript輕松修改Minecraft

typescript 使用by Josh Wulf通過喬什沃爾夫(Josh Wulf) 如何使用TypeScript輕松修改Minecraft (How to modify Minecraft the easy way with TypeScript) Usually, modifying Minecraft requires coding in Java, and a lot of scaffolding. Now you can write and share Min…

Python:在Pandas數據框中查找缺失值

How to find Missing values in a data frame using Python/Pandas如何使用Python / Pandas查找數據框中的缺失值 介紹&#xff1a; (Introduction:) When you start working on any data science project the data you are provided is never clean. One of the most common …

監督學習-回歸分析

一、數學建模概述 監督學習&#xff1a;通過已有的訓練樣本進行訓練得到一個最優模型&#xff0c;再利用這個模型將所有的輸入映射為相應的輸出。監督學習根據輸出數據又分為回歸問題&#xff08;regression&#xff09;和分類問題&#xff08;classfication&#xff09;&#…

leetcode 54. 螺旋矩陣(遞歸)

給你一個 m 行 n 列的矩陣 matrix &#xff0c;請按照 順時針螺旋順序 &#xff0c;返回矩陣中的所有元素。 示例 1&#xff1a; 輸入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 輸出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 輸入&#xff1a;matrix [[1,…

微服務架構技能

2019獨角獸企業重金招聘Python工程師標準>>> 微服務架構技能 博客分類&#xff1a; 架構 &#xff08;StuQ 微服務技能圖譜&#xff09; 2課程簡介 本課程分為基礎篇和高級篇兩部分&#xff0c;旨在通過完整的案例&#xff0c;呈現微服務的開發、測試、構建、部署、…

phpstorm 調試_PhpStorm中的多用戶調試

phpstorm 調試by Ray Naldo雷納爾多(Ray Naldo) PhpStorm中的多用戶調試 (Multi-User Debugging in PhpStorm) 使用Xdebug和DBGp代理 (Using Xdebug and DBGp Proxy) “Er, wait a minute… Don’t you just use xdebug.remote_connect_back which has been introduced since …

Tableau Desktop認證:為什么要關心以及如何通過

Woah, Tableau!哇&#xff0c;Tableau&#xff01; By now, almost everyone’s heard of the data visualization software that brought visual analytics to the public. Its intuitive drag and drop interface makes connecting to data, creating graphs, and sharing d…

約束布局constraint-layout導入失敗的解決方案 - 轉

今天有同事用到了約束布局&#xff0c;但是導入我的工程出現錯誤 **提示錯誤&#xff1a; Could not find com.Android.support.constraint:constraint-layout:1.0.0-alpha3** 我網上查了一下資料&#xff0c;都說是因為我的androidStudio版本是最新的穩定版導入這個包就會報這…

算法復習:冒泡排序

思想&#xff1a;對于一個列表,每個數都是一個"氣泡 "&#xff0c;數字越大表示"越重 "&#xff0c;最重的氣泡移動到列表最后一位&#xff0c;冒泡排序后的結果就是“氣泡”按照它們的重量依次移動到列表中它們相應的位置。 算法&#xff1a;搜索整個列表…

leetcode 59. 螺旋矩陣 II(遞歸)

給你一個正整數 n &#xff0c;生成一個包含 1 到 n2 所有元素&#xff0c;且元素按順時針順序螺旋排列的 n x n 正方形矩陣 matrix 。 示例 1&#xff1a; 輸入&#xff1a;n 3 輸出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 解題思路 按層進行數字的填充&#xff0c;每一層…

前端基礎進階(七):函數與函數式編程

縱觀JavaScript中所有必須需要掌握的重點知識中&#xff0c;函數是我們在初學的時候最容易忽視的一個知識點。在學習的過程中&#xff0c;可能會有很多人、很多文章告訴你面向對象很重要&#xff0c;原型很重要&#xff0c;可是卻很少有人告訴你&#xff0c;面向對象中所有的重…

期權數據 獲取_我如何免費獲得期權數據

期權數據 獲取by Harry Sauers哈里紹爾斯(Harry Sauers) 我如何免費獲得期權數據 (How I get options data for free) 網頁抓取金融簡介 (An introduction to web scraping for finance) Ever wished you could access historical options data, but got blocked by a paywall…

顯示與刪除使用工具

右擊工具菜單欄中的空白處選擇自定義 在彈出的自定義菜單中選擇命令選項在選擇想要往里面添加工具的菜單&#xff0c;之后在選擇要添加的工具 若想要刪除工具欄中的某個工具&#xff0c;在打開自定義菜單后&#xff0c;按住鼠標左鍵拖動要刪除工具到空白處 例如 轉載于:https:/…

js值的拷貝和值的引用_到達P值的底部:直觀的解釋

js值的拷貝和值的引用介紹 (Introduction) Welcome to this lesson on calculating p-values.歡迎參加有關計算p值的課程。 Before we jump into how to calculate a p-value, it’s important to think about what the p-value is really for.在我們開始計算p值之前&#xff…

leetcode 115. 不同的子序列(dp)

給定一個字符串 s 和一個字符串 t &#xff0c;計算在 s 的子序列中 t 出現的個數。 字符串的一個 子序列 是指&#xff0c;通過刪除一些&#xff08;也可以不刪除&#xff09;字符且不干擾剩余字符相對位置所組成的新字符串。&#xff08;例如&#xff0c;“ACE” 是 “ABCDE…

監督學習-KNN最鄰近分類算法

分類&#xff08;Classification&#xff09;指的是從數據中選出已經分好類的訓練集&#xff0c;在該訓練集上運用數據挖掘分類的技術建立分類模型&#xff0c;從而對沒有分類的數據進行分類的分析方法。 分類問題的應用場景&#xff1a;用于將事物打上一個標簽&#xff0c;通常…

istio 和 kong_如何啟動和運行Istio

istio 和 kongby Chris Cooney克里斯庫尼(Chris Cooney) 如何啟動和運行Istio (How to get Istio up and running) 而一旦完成&#xff0c;您就可以做的瘋狂的事情。 (And the crazy stuff you can do once it is.) The moment you get Istio working on your cluster, it fee…

js練習--貪吃蛇(轉)

最近一直在看javascript&#xff0c;但是發現不了動力。就開始想找動力&#xff0c;于是在網上找到了一個用js寫的貪吃蛇游戲。奈何還不會用git&#xff0c;就只能先這樣保存著。哈哈哈&#xff0c;這也算第一篇博客了&#xff0c;以后會堅持用自己的代碼寫博客的&#xff0c;下…

bzoj千題計劃169:bzoj2463: [中山市選2009]誰能贏呢?

http://www.lydsy.com/JudgeOnline/problem.php?id2463 n為偶數時&#xff0c;一定可以被若干個1*2 矩形覆蓋 先手每次從矩形的一端走向另一端&#xff0c;后手每次走向一個新的矩形 所以先手必勝 n為奇數時&#xff0c;先手走完一步后&#xff0c;剩下同n為偶數 所以先手必敗…

無監督學習-主成分分析和聚類分析

聚類分析&#xff08;cluster analysis&#xff09;是將一組研究對象分為相對同質的群組&#xff08;clusters&#xff09;的統計分析技術&#xff0c;即將觀測對象的群體按照相似性和相異性進行不同群組的劃分&#xff0c;劃分后每個群組內部各對象相似度很高&#xff0c;而不…