※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。
觀察者模式簡述
觀察者(Observer)模式的定義:指多個對象間存在一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。這種模式有時又稱作發布-訂閱模式、模型-視圖模式,它是對象行為型模式。
觀察者模式結構與實現
實現觀察者模式時要注意具體目標對象和具體觀察者對象之間不能直接調用,否則將使兩者之間緊密耦合起來,這違反了面向對象的設計原則。
觀察者模式主要結構如下:
- 抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用於保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。
- 具體主題(Concrete Subject)角色:也叫具體目標類,它實現抽象目標中的通知方法,當具體主題的內部狀態發生改變時,通知所有註冊過的觀察者對象。
- 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被調用。
- 具體觀察者(Concrete Observer)角色:實現抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態。
uml圖如下:
觀察者模式代碼實現如下:
/** * 抽象主題(被觀察角色) */ public abstract class Subject{ //觀察者list集合(聚集對象) protected List<Observer> observerList=new ArrayList<Observer>(); //註冊觀察者 public void addObserver(Observer observer){ observerList.add(observer); } //刪除觀察者 public void removeObserver(Observer observer){ if(observerList.contains(observer)){ observerList.remove(observer); } } //通知觀察者 public abstract void notifyObserver(); } /** * 具體主題角色類(被觀察的類) */ public class ConcreteSubject extends Subject{ @Override public void notifyObserver() { System.out.println("被觀察者發現變化了..."); for(Observer observer:super.observerList){ observer.update(); } } } /** * 抽象觀察者 */ public interface Observer { public void update(); } /** * 具體觀察者類 */ public class ConcreteObserver1 implements Observer { @Override public void update() { System.out.println("observe1 更新了"); } } /** * 具體觀察者 */ public class ConcreteObserver2 implements Observer { @Override public void update() { System.out.println("observer2 發生變更"); } } /** * 客戶端測試類 */ public class ObserverClient { public static void main(String[] args) { Subject subject=new ConcreteSubject(); Observer observer1=new ConcreteObserver1(); Observer observer2=new ConcreteObserver2(); subject.addObserver(observer1); subject.addObserver(observer2); //具體主題發生變化通知觀察者。 subject.notifyObserver(); } }
觀察者模式案例
1.利用觀察者模式設計一個程序,分析“人民幣匯率”的升值或貶值對進口公司的進口產品成本或出口公司的出口產品收入以及公司的利潤率的影響。
分析:。被觀察的抽象主題對象就是匯率Rate,以人民幣匯率RMBRate為具體主題。以公司Company為抽象觀察者,出口公司ExportCompany為具體的觀察者,進口公司ImportCompany為具體的觀察者,人民幣匯率(具體主題角色)升值時,進口公司(具體觀察者對象)的進口產品成本降低且利潤率提升,出口公司(具體觀察者對象)的出口產品收入降低且利潤率降低;當人民幣匯率貶值時,進口公司的進口產品成本提升且利潤率降低,出口公司的出口產品收入提升且利潤率提升。總而言之當主題角色匯率發生變化時,觀察者Company的利潤也相應發生變化。
uml圖如下:
代碼實現如下:
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污
/** * 抽象觀察者 */ public interface Company { void update(int changeRate); } /** * 具體觀察者進口公司ExportCompany */ public class ExportCompany implements Company { @Override public void update(int changeRate) { if(changeRate>=0){ System.out.println("人民幣匯率升值"+changeRate+"個基點,降低了進口產品成本,提升了進口公司利潤率"); } else { System.out.println("人民幣匯率貶值"+(0-changeRate)+"個基點,提升了進口產品成本,降低了進口公司利潤率。"); } } } /** * 具體觀察者進口公司importCompany */ public class ImportCompany implements Company { @Override public void update(int changeRate) { if(changeRate>=0){ System.out.println("人民幣匯率升值"+changeRate+"個基點,降低了進口產品成本,提升了進口公司利潤率"); } else { System.out.println("人民幣匯率貶值"+(0-changeRate)+"個基點,提升了進口產品成本,降低了進口公司利潤率。"); } } } /** * 抽象主題角色 */ public abstract class Rate { //觀察者company對象list集合 protected List<Company> companyList=new ArrayList<Company>(); //增加觀察者company對象 public void addObserver(Company company){ companyList.add(company); } //刪除觀察者company對象 public void removeObserver(Company company){ companyList.remove(company); } public abstract void change(int rateChange); } /** * 具體主題對象人民幣匯率RMBRate */ public class RMBRate extends Rate { @Override public void change(int rateChange) { for (Company company:super.companyList){ company.update(rateChange); } } } /** * 匯率變化觀察者模式實現客戶端類 */ public class RateClient { public static void main(String[] args) { //具體觀察對像進口公司 Company importCompany=new ImportCompany(); //具體觀察者對象出口公司 Company exportCompany=new ExportCompany(); //具體主題角色人民幣對象 Rate rmbRate=new RMBRate(); //增添觀察者對象 rmbRate.addObserver(importCompany); rmbRate.addObserver(exportCompany); //匯率提升 rmbRate.change(2); //匯率降低 rmbRate.change(-3); } }
2.事件監聽模式就是利用觀察者模式實現的,java的awt窗體程序就是用觀察者模式實現的,在軟件幵發中窗體程序,界面程序都是基於事件監聽模式實現。現在以awt的Button的點擊事件為例,來了解一下事件監聽模式。首先創建一個按鈕Button類(事件源對象,被觀察者對象),將按鈕點擊監聽器註冊在Button上,當用戶點擊按鈕時,會產生一個按鈕點擊事件 ButtonClickEvent,將點擊事件傳給按鈕點擊監聽器 ButtonClickListener,監聽器做出相應的動作。
uml圖如下:
代碼實現如下:
/** * 自定義按鈕類,事件源對象 */ public class Button { private String buttonName; protected List<Listener> listenerlist = new ArrayList<Listener>(); //註冊監聽器 public void addListener(Listener listener){ listenerlist.add(listener); } //移除監聽器 public void removeListener(Listener listener){ listenerlist.remove(listener); } //點擊方法 public void press(){ ButtonClickEvent event=new ButtonClickEvent(this); for (Listener listener:listenerlist){ listener.actionPerformed(event); } } public String getButtonName() { return buttonName; } public void setButtonName(String buttonName) { this.buttonName = buttonName; } } package cn.ck.observer.v4; import java.util.EventObject; /** * 按鈕點擊事件 */ public class ButtonClickEvent extends EventObject {
private Object source; public ButtonClickEvent(Object source){ this.source=source; } } /** * 抽象監聽器 */ public interface Listener { public void actionPerformed(ButtonClickEvent event); } /** * 按鈕點擊監聽器 具體觀察者 */ public class ButtonClickListener implements Listener { @Override public void actionPerformed(ButtonClickEvent event) { Button button= (Button) event.getSource(); System.out.println(button.getButtonName()+"按鈕被點擊了..."); } } /** * 按鈕事件測試類 */ public class ButtonClient { public static void main(String[] args) { Button b1=new Button(); Listener listener=new ButtonClickListener(); b1.setButtonName("button1"); Button b2=new Button(); b2.setButtonName("button2"); b1.addListener(listener); b2.addListener(listener); b1.press(); b2.press(); } }
jdk的觀察模式通過 java.util.Observable 類和 java.util.Observer 接口定義的,只要實現它們的子類就可以編寫觀察者模式實例。
1. Observable類
Observable 類是抽象目標類,它有一個 Vector 集合,用於保存所有要通知的觀察者對象,下面來介紹它最重要的 3 個方法。
- void addObserver(Observer o) 方法:用於將新的觀察者對象添加到向中Vector集合(線程安全)。
- void notifyObservers(Object arg) 方法:調用Vector集合中的所有觀察者對象的 update。方法,通知它們數據發生改變。通常越晚加入向量的觀察者越先得到通知。
- void setChange() 方法:用來設置一個 boolean 類型的內部標誌位,註明目標對象發生了變化。當它為真時,notifyObservers() 才會通知觀察者。
2. Observer 接口
Observer 接口是抽象觀察者,它監視目標對象的變化,當目標對象發生變化時,觀察者得到通知,並調用 void update(Observable o,Object arg) 方法,進行相應的工作。
還是以上面匯率的例子為例,用jdk的抽象觀察者,抽象目標類實現觀察者模式,具體代碼如下:
/** * 具體主題對象人民幣匯率RMBRate */ public class RMBRate extends Observable{ public void change (int rateChange) { //changed變成true super.setChanged(); super.notifyObservers(rateChange); } } /** * 具體觀察者進口公司ExportCompany */ public class ExportCompany implements Observer{ @Override public void update(Observable o, Object arg) { int changeRate= (int) arg; if(changeRate>=0){ System.out.println("人民幣匯率升值"+changeRate+"個基點,降低了進口產品成本,提升了進口公司利潤率"); } else { System.out.println("人民幣匯率貶值"+(0-changeRate)+"個基點,提升了進口產品成本,降低了進口公司利潤率。"); } } } /** * 具體觀察者進口公司importCompany */ public class ImportCompany implements Observer { @Override public void update(Observable o, Object arg) { int changeRate= (int) arg; if(changeRate>=0){ System.out.println("人民幣匯率升值"+changeRate+"個基點,降低了進口產品成本,提升了進口公司利潤率"); } else { System.out.println("人民幣匯率貶值"+(0-changeRate)+"個基點,提升了進口產品成本,降低了進口公司利潤率。"); } } } /** * 匯率變化觀察者模式實現客戶端類 */ public class RateClient { public static void main(String[] args) { //具體觀察對像進口公司 Observer importCompany=new ImportCompany(); //具體觀察者對象出口公司 Observer exportCompany=new ExportCompany(); //具體主題角色人民幣對象 RMBRate rmbRate=new RMBRate(); //增添觀察者對象 rmbRate.addObserver(importCompany); rmbRate.addObserver(exportCompany); //匯率提升 rmbRate.change(2); //匯率降低 rmbRate.change(-3); } }
觀察者模式優點與缺點
1.觀察者模式優點
- 降低了目標與觀察者之間的耦合關係,兩者之間是抽象耦合關係。
- 目標與觀察者之間建立了一套觸發機制。
2.觀察者模式缺點
- 目標與觀察者之間的依賴關係並沒有完全解除,而且有可能出現循環引用(可以通過事件類引用一個目標對象解決這個問題)。
- 當觀察者對象很多時,通知的發布會花費很多時間,影響程序的效率。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污