日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

求职华为,被问观察者模式,从没有这种体验!!!

發(fā)布時間:2023/12/4 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 求职华为,被问观察者模式,从没有这种体验!!! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

求職華為,被問觀察者模式,從沒有這種體驗!!!

  • 模式的定義與特點
  • 模式的結(jié)構(gòu)與實現(xiàn)
    • 1. 模式的結(jié)構(gòu)
    • 2. 模式的實現(xiàn)
  • 模式的應(yīng)用實例
  • 模式的應(yīng)用場景
    • 模式的擴展
    • 1. Observable類
    • 2. Observer 接口

[

觀察者模式可以說是非常貼近我們生活的一個設(shè)計模式,為什么這么說呢?哲學上有這么一種說法,叫做“萬事萬物皆有聯(lián)系”,原意是說世上沒有孤立存在的事物,但其實也可以理解為任何一個事件的發(fā)生必然由某個前置事件引起,也必然會導(dǎo)致另一個后置事件。

我們的生活中,充斥著各種各樣的相互聯(lián)系的事件,而觀察者模式,主要就是用于處理這種事件的一套解決方案。

模式的定義與特點

觀察者(Observer)模式的定義:指多個對象間存在一對多的依賴關(guān)系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。這種模式有時又稱作發(fā)布-訂閱模式、模型-視圖模式,它是對象行為型模式。

觀察者模式是一種對象行為型模式,其主要優(yōu)點如下。

降低了目標與觀察者之間的耦合關(guān)系,兩者之間是抽象耦合關(guān)系。符合依賴倒置原則。
目標與觀察者之間建立了一套觸發(fā)機制。
它的主要缺點如下。

目標與觀察者之間的依賴關(guān)系并沒有完全解除,而且有可能出現(xiàn)循環(huán)引用。
當觀察者對象很多時,通知的發(fā)布會花費很多時間,影響程序的效率。

模式的結(jié)構(gòu)與實現(xiàn)

實現(xiàn)觀察者模式時要注意具體目標對象和具體觀察者對象之間不能直接調(diào)用,否則將使兩者之間緊密耦合起來,這違反了面向?qū)ο蟮脑O(shè)計原則。

1. 模式的結(jié)構(gòu)

觀察者模式的主要角色如下。

  • 抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用于保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。

  • 具體主題(Concrete Subject)角色:也叫具體目標類,它實現(xiàn)抽象目標中的通知方法,當具體主題的內(nèi)部狀態(tài)發(fā)生改變時,通知所有注冊過的觀察者對象。

  • 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被調(diào)用。

  • 具體觀察者(Concrete Observer)角色:實現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態(tài)。
    觀察者模式的結(jié)構(gòu)圖如圖 1 所示。

2. 模式的實現(xiàn)

觀察者模式的實現(xiàn)代碼如下:

package net.biancheng.c.observer; import java.util.*; public class ObserverPattern {public static void main(String[] args) {Subject subject = new ConcreteSubject();Observer obs1 = new ConcreteObserver1();Observer obs2 = new ConcreteObserver2();subject.add(obs1);subject.add(obs2);subject.notifyObserver();} } //抽象目標 abstract class Subject {protected List<Observer> observers = new ArrayList<Observer>();//增加觀察者方法public void add(Observer observer) {observers.add(observer);}//刪除觀察者方法public void remove(Observer observer) {observers.remove(observer);}public abstract void notifyObserver(); //通知觀察者方法 }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 //具體目標 class ConcreteSubject extends Subject {public void notifyObserver() {System.out.println("具體目標發(fā)生改變...");System.out.println("--------------");for (Object obs : observers) {((Observer) obs).response();}} } //抽象觀察者 interface Observer {void response(); //反應(yīng) } //具體觀察者1 class ConcreteObserver1 implements Observer {public void response() {System.out.println("具體觀察者1作出反應(yīng)!");} }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 //具體觀察者1 class ConcreteObserver2 implements Observer {public void response() {System.out.println("具體觀察者2作出反應(yīng)!");} }

模式的應(yīng)用實例

【例1】利用觀察者模式設(shè)計一個程序,分析“人民幣匯率”的升值或貶值對進口公司進口產(chǎn)品成本或出口公司的出口產(chǎn)品收入以及公司利潤率的影響。
分析:當“人民幣匯率”升值時,進口公司的進口產(chǎn)品成本降低且利潤率提升,出口公司的出口產(chǎn)品收入降低且利潤率降低;當“人民幣匯率”貶值時,進口公司的進口產(chǎn)品成本提升且利潤率降低,出口公司的出口產(chǎn)品收入提升且利潤率提升。

這里的匯率(Rate)類是抽象目標類,它包含了保存觀察者(Company)的 List 和增加/刪除觀察者的方法,以及有關(guān)匯率改變的抽象方法 change(int number);而人民幣匯率(RMBrate)類是具體目標, 它實現(xiàn)了父類的 change(int number) 方法,即當人民幣匯率發(fā)生改變時通過相關(guān)公司;公司(Company)類是抽象觀察者,它定義了一個有關(guān)匯率反應(yīng)的抽象方法 response(int number);進口公司(ImportCompany)類和出口公司(ExportCompany)類是具體觀察者類,它們實現(xiàn)了父類的 response(int number) 方法,即當它們接收到匯率發(fā)生改變的通知時作為相應(yīng)的反應(yīng)。圖 2 所示是其結(jié)構(gòu)圖。
[

程序代碼如下:

package net.biancheng.c.observer; import java.util.*; public class RMBrateTest {public static void main(String[] args) {Rate rate = new RMBrate();Company watcher1 = new ImportCompany();Company watcher2 = new ExportCompany();rate.add(watcher1);rate.add(watcher2);rate.change(10);rate.change(-9);}//加入Java開發(fā)交流君樣:756584822一起吹水聊天 } //抽象目標:匯率 abstract class Rate {protected List<Company> companys = new ArrayList<Company>();//增加觀察者方法public void add(Company company) {companys.add(company);}//刪除觀察者方法public void remove(Company company) {companys.remove(company);}public abstract void change(int number); } //具體目標:人民幣匯率 class RMBrate extends Rate {public void change(int number) {for (Company obs : companys) {((Company) obs).response(number);}}//加入Java開發(fā)交流君樣:756584822一起吹水聊天 } //抽象觀察者:公司 interface Company {void response(int number); } //具體觀察者1:進口公司 class ImportCompany implements Company {public void response(int number) {if (number > 0) {System.out.println("人民幣匯率升值" + number + "個基點,降低了進口產(chǎn)品成本,提升了進口公司利潤率。");} else if (number < 0) {System.out.println("人民幣匯率貶值" + (-number) + "個基點,提升了進口產(chǎn)品成本,降低了進口公司利潤率。");}} } //具體觀察者2:出口公司 class ExportCompany implements Company {public void response(int number) {if (number > 0) {System.out.println("人民幣匯率升值" + number + "個基點,降低了出口產(chǎn)品收入,降低了出口公司的銷售利潤率。");} else if (number < 0) {System.out.println("人民幣匯率貶值" + (-number) + "個基點,提升了出口產(chǎn)品收入,提升了出口公司的銷售利潤率。");}} }


現(xiàn)在用“觀察者模式”來實現(xiàn)該事件處理模型。
首先,定義一個鈴聲事件(RingEvent)類,它記錄了鈴聲的類型(上課鈴聲/下課鈴聲)。
再定義一個學校的鈴(BellEventSource)類,它是事件源,是觀察者目標類,該類里面包含了監(jiān)聽器容器 listener,可以綁定監(jiān)聽者(學生或老師),并且有產(chǎn)生鈴聲事件和通知所有監(jiān)聽者的方法。
然后,定義鈴聲事件監(jiān)聽者(BellEventListener)類,它是抽象觀察者,它包含了鈴聲事件處理方法 heardBell(RingEvent e)。
最后,定義老師類(TeachEventListener)和學生類(StuEventListener),它們是事件監(jiān)聽器,是具體觀察者,聽到鈴聲會去上課或下課。圖 4 給出了學校鈴聲事件處理程序的結(jié)構(gòu)。


程序代碼如下:

package net.biancheng.c.observer; import java.util.*; public class BellEventTest {public static void main(String[] args) {BellEventSource bell = new BellEventSource(); //鈴(事件源)bell.addPersonListener(new TeachEventListener()); //注冊監(jiān)聽器(老師)bell.addPersonListener(new StuEventListener()); //注冊監(jiān)聽器(學生)bell.ring(true); //打上課鈴聲System.out.println("------------");bell.ring(false); //打下課鈴聲}//加入Java開發(fā)交流君樣:756584822一起吹水聊天 } //鈴聲事件類:用于封裝事件源及一些與事件相關(guān)的參數(shù) class RingEvent extends EventObject {private static final long serialVersionUID = 1L;private boolean sound; //true表示上課鈴聲,false表示下課鈴聲public RingEvent(Object source, boolean sound) {super(source);this.sound = sound;}public void setSound(boolean sound) {this.sound = sound;}public boolean getSound() {return this.sound;} } //目標類:事件源,鈴 class BellEventSource {private List<BellEventListener> listener; //監(jiān)聽器容器public BellEventSource() {listener = new ArrayList<BellEventListener>();}//給事件源綁定監(jiān)聽器public void addPersonListener(BellEventListener ren) {listener.add(ren);}//事件觸發(fā)器:敲鐘,當鈴聲sound的值發(fā)生變化時,觸發(fā)事件。public void ring(boolean sound) {String type = sound ? "上課鈴" : "下課鈴";System.out.println(type + "響!");RingEvent event = new RingEvent(this, sound);notifies(event); //通知注冊在該事件源上的所有監(jiān)聽器}//加入Java開發(fā)交流君樣:756584822一起吹水聊天//當事件發(fā)生時,通知綁定在該事件源上的所有監(jiān)聽器做出反應(yīng)(調(diào)用事件處理方法)protected void notifies(RingEvent e) {BellEventListener ren = null;Iterator<BellEventListener> iterator = listener.iterator();while (iterator.hasNext()) {ren = iterator.next();ren.heardBell(e);}} } //抽象觀察者類:鈴聲事件監(jiān)聽器 interface BellEventListener extends EventListener {//事件處理方法,聽到鈴聲public void heardBell(RingEvent e); } //具體觀察者類:老師事件監(jiān)聽器 class TeachEventListener implements BellEventListener {public void heardBell(RingEvent e) {if (e.getSound()) {System.out.println("老師上課了...");} else {System.out.println("老師下課了...");}} }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 //具體觀察者類:學生事件監(jiān)聽器 class StuEventListener implements BellEventListener {public void heardBell(RingEvent e) {if (e.getSound()) {System.out.println("同學們,上課了...");} else {System.out.println("同學們,下課了...");}} }

模式的應(yīng)用場景

在軟件系統(tǒng)中,當系統(tǒng)一方行為依賴另一方行為的變動時,可使用觀察者模式松耦合聯(lián)動雙方,使得一方的變動可以通知到感興趣的另一方對象,從而讓另一方對象對此做出響應(yīng)。
通過前面的分析與應(yīng)用實例可知觀察者模式適合以下幾種情形。

  • 對象間存在一對多關(guān)系,一個對象的狀態(tài)發(fā)生改變會影響其他對象。
  • 當一個抽象模型有兩個方面,其中一個方面依賴于另一方面時,可將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復(fù)用。
  • 實現(xiàn)類似廣播機制的功能,不需要知道具體收聽者,只需分發(fā)廣播,系統(tǒng)中感興趣的對象會自動接收該廣播。
  • 多層級嵌套使用,形成一種鏈式觸發(fā)機制,使得事件具備跨域(跨越兩種觀察者類型)通知。

模式的擴展

在 Java 中,通過 java.util.Observable 類和 java.util.Observer 接口定義了觀察者模式,只要實現(xiàn)它們的子類就可以編寫觀察者模式實例。

1. Observable類

Observable 類是抽象目標類,它有一個 Vector 向量,用于保存所有要通知的觀察者對象,下面來介紹它最重要的 3 個方法。

  • void addObserver(Observer o) 方法:用于將新的觀察者對象添加到向量中。
  • void notifyObservers(Object arg) 方法:調(diào)用向量中的所有觀察者對象的 update() 方法,通知它們數(shù)據(jù)發(fā)生改變。通常越晚加入向量的觀察者越先得到通知。
  • void setChange() 方法:用來設(shè)置一個 boolean 類型的內(nèi)部標志位,注明目標對象發(fā)生了變化。當它為真時,notifyObservers() 才會通知觀察者。

2. Observer 接口

Observer 接口是抽象觀察者,它監(jiān)視目標對象的變化,當目標對象發(fā)生變化時,觀察者得到通知,并調(diào)用 void update(Observable o,Object arg) 方法,進行相應(yīng)的工作。

【例3】利用 Observable 類和 Observer 接口實現(xiàn)原油期貨的觀察者模式實例。

分析:當原油價格上漲時,空方傷心,多方局興;當油價下跌時,空方局興,多方傷心。本實例中的抽象目標(Observable)類在 Java 中已經(jīng)定義,可以直接定義其子類,即原油期貨(OilFutures)類,它是具體目標類,該類中定義一個SetPriCe(float price) 方法,當原油數(shù)據(jù)發(fā)生變化時調(diào)用其父類的 notifyObservers(Object arg) 方法來通知所有觀察者;另外,本實例中的抽象觀察者接口(Observer)在 Java 中已經(jīng)定義,只要定義其子類,即具體觀察者類(包括多方類 Bull 和空方類 Bear),并實現(xiàn)update(Observable o,Object arg)方法即可。圖 5 所示是其結(jié)構(gòu)圖。
[

package net.biancheng.c.observer; import java.util.Observer; import java.util.Observable; public class CrudeOilFutures {public static void main(String[] args) {OilFutures oil = new OilFutures();Observer bull = new Bull(); //多方Observer bear = new Bear(); //空方oil.addObserver(bull);oil.addObserver(bear);oil.setPrice(10);oil.setPrice(-8);}//加入Java開發(fā)交流君樣:756584822一起吹水聊天 } //具體目標類:原油期貨 class OilFutures extends Observable {private float price;public float getPrice() {return this.price;}public void setPrice(float price) {super.setChanged(); //設(shè)置內(nèi)部標志位,注明數(shù)據(jù)發(fā)生變化super.notifyObservers(price); //通知觀察者價格改變了this.price = price;} } //具體觀察者類:多方 class Bull implements Observer {public void update(Observable o, Object arg) {Float price = ((Float) arg).floatValue();if (price > 0) {System.out.println("油價上漲" + price + "元,多方高興了!");} else {System.out.println("油價下跌" + (-price) + "元,多方傷心了!");}} } //具體觀察者類:空方 class Bear implements Observer {public void update(Observable o, Object arg) {Float price = ((Float) arg).floatValue();if (price > 0) {System.out.println("油價上漲" + price + "元,空方傷心了!");} else {System.out.println("油價下跌" + (-price) + "元,空方高興了!");}} }

最后,祝大家早日學有所成,拿到滿意offer

總結(jié)

以上是生活随笔為你收集整理的求职华为,被问观察者模式,从没有这种体验!!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。