請在后臺配置參數,參數名稱:topads
編程語言 php java

java設計模式-觀察者模式Observer

java HTML我幫您 1年前  7803次瀏覽
觀察者模式(Observer Pattern)用于對象關系為一對多的情況。比如說,一個對象發生改變,這個對象的依賴對象會自動接收通知。觀察者模型屬于表現型。

下面我們就來看看觀察者模式的組成部分。
1) 抽象目標角色(Subject):目標角色知道它的觀察者,可以有任意多個觀察者觀察同一個目標。并且提供注冊和刪除觀察者對象的接口。目標角色往往由抽象類或者接口來實現。
2) 抽象觀察者角色(Observer):為那些在目標發生改變時需要獲得通知的對象定義一個更新接口。抽象觀察者角色主要由抽象類或者接口來實現。
3) 具體目標角色(Concrete Subject):將有關狀態存入各個Concrete Observer對象。當它的狀態發生改變時, 向它的各個觀察者發出通知。
4) 具體觀察者角色(Concrete Observer):存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer的更新接口以使自身狀態與目標的狀態保持一致。在本角色內也可以維護一個指向Concrete Subject對象的引用。
舉例
package com.html580.observer;

import java.util.ArrayList;
import java.util.List;

interface Observer {
public void update();
}

interface Subject {
/* 增加觀察者 */
public void add(Observer observer);

/* 刪除觀察者 */
public void del(Observer observer);

/* 通知所有的觀察者 */
public void notifyObservers();

/* 自身的操作 */
public void operation();

/* 獲取主題的State */
public int getState();

/* 更新主題State */
public void setState(int state);

}

abstract class AbstractSubject implements Subject {
private List observers = new ArrayList();
private int state;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
notifyObservers();
}

public void add(Observer observer) {
observers.add(observer);
}

public void del(Observer observer) {
observers.remove(observer);
}

public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}

class MySubject extends AbstractSubject {

@Override
public void operation() {
System.out.println("update self!");
notifyObservers();
}

}

abstract class AbstractObserver implements Observer {
protected Subject subject;

public abstract void update();
}

class Observer1 extends AbstractObserver {

public Observer1(Subject subject){
this.subject = subject;
this.subject.add(this);
}

@Override
public void update() {
System.out.println("observer1 has received!");
if(this.subject.getState()!=0){
System.out.println("received State:"+this.subject.getState());
}
}
}

class Observer2 extends AbstractObserver {

public Observer2(Subject subject){
this.subject = subject;
this.subject.add(this);
}

@Override
public void update() {
System.out.println("observer2 has received!");
if(this.subject.getState()!=0){
System.out.println("received State:"+this.subject.getState());
}
}
}

public class Client {

public static void main(String<> args) {
Subject sub = new MySubject();
new Observer1(sub);
new Observer2(sub);
sub.operation();

sub.setState(1);
}

}
Observer模式定義對象間的一對多的依賴關系,當一個對象(被觀察者)的狀態發生改變時, 所有依賴于它的對象(觀察者)都得到通知并被自動更新。JDK里提供的observer設計模式的實現由java.util.Observable類和 java.util.Observer接口組成。
1. Observable和Observer對象是一對多的關系,也就是說一旦Observable對象狀態變化,它就要負責通知所有和它有關系的Observer對象,然后做相應的改變.
1. Observable對象不會主動去通知各個具體的Observer對象其狀態發生了變化,而是提供一個注冊接口供Observer對象使用,任何一個Observer對象如果想要被通知,則可以使用這個接口來注冊.
3. 在Observable中有一個集合和一個狀態控制開關,所有注冊了通知的Observer對象會被保存在這個集合中.這個控制開關就是用來控制Observable是否發生了變化,一旦發生了變化,就通知所有的Observer對象更新狀態.
下面是模擬了燒水的過程實例
涉及三個對象,Heater(熱水器),Display(顯示器),Alarm(報警器).
模擬過程:為了便于運行,水的初始化溫度為90,沸點為95,顯示器依據熱水器顯示溫度,顯示器顯示溫度為95時,報警器開始報警。明顯可以看出Heater是subject ,Display 是它的 Obsrver,同時Display亦是subject,因為它要被報警器觀察,所以Alarm是Display的Observer.
package com.html580.observer;

import java.util.Observable;
//Heater類
class Heater extends Observable {

private int temperature;

public int getTemperature() {
return temperature;
}

public void setTemperature(int temperature) {
this.temperature = temperature;
}

public void boilWater() {
for (int i = 90; i < 110; i++) {
temperature = i;
this.setChanged();
this.notifyObservers();
}
}

}

// Display類

class Display extends Observable implements java.util.Observer {

private String status = "未開";

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public void update(Observable o, Object arg) {
this.displayTemperature(((Heater) o).getTemperature());
}

private void displayTemperature(int temperature) {
if (temperature > 100) {
this.setStatus("沸騰");
this.setChanged();
this.notifyObservers(temperature);
}
System.out.println("狀態: " + status + " 現在溫度: " + temperature);

}

}

// Alarm類
class Alarm implements java.util.Observer {

public void update(Observable arg0, Object arg1) {
this.makeAlarm((Integer) arg1);
}

private void makeAlarm(int temperature) {
System.out.println("嘀嘀嘀。。。水已經燒開了");
// System.out.println("現在水溫是: " + temperature);
}

}

// Client2測試入口類
public class Client2 {

public static void main(String<> args) {

Heater heater = new Heater();
Display display = new Display();
Alarm alarm = new Alarm();
heater.addObserver(display);
display.addObserver(alarm);
heater.boilWater();

}

}
優點

支持松耦合和減少依賴性??蛻舳瞬辉僖蕾囉谟^察器,因為通過使用主體和 Observer 接口對客戶端進行了隔離。許多框架具有此優點,在這些框架中的應用程序組件可以注冊為當(低級)框架事件發生時得到通知。結果,框架將調用應用程序組件,但不會依賴于它。
觀察器數目可變。觀察器可以在運行時附加和分離,因為主體對于觀察器數目沒有任何假定。此功能在這樣的情況下是很有用的:觀察器數在設計時是未知的。例如,如果用戶在應用程序中打開的每個窗口都需要一個觀察器。

缺點

性能降低。在許多實現中,觀察器的 update() 方法可能與主體在同一線程中執行。如果觀察器列表很長,則執行 Notify() 方法可能需要很長時間。抽取對象依賴性并不意味著添加觀察器對應用程序沒有任何影響。
內存泄漏。在 Observer 中使用的回調機制(當對象注冊為以后調用時)會產生一個常見的錯誤,從而導致內存泄漏,甚至是在托管的 C# 代碼中。假定觀察器超出作用范圍,但忘記取消對主體的訂閱,那么主體仍然保留對觀察器的引用。此引用防止垃圾收集在主體對象也被破壞之前重新分配與觀察器關聯的內存。如果觀察器的生存期比主體的生存期短得多(通常是這種情況),則會導致嚴重的內存泄漏。
隱藏的依賴項。觀察器的使用將顯式依賴性(通過方法調用)轉變為隱式依賴性(通過觀察器)。如果在整個應用程序中廣泛地使用觀察器,則開發人員幾乎不可能通過查看源代碼來了解所發生的事情。這樣,就使得了解代碼更改的含意非常困難。此問題隨傳播級別急劇增大(例如,充當 Subject 的觀察器)。因此,應該僅在少數定義良好的交互(如 Model-View-Controller 模式中模型和視圖之間的交互)中使用觀察器。最好不要在域對象之間使用觀察器。
測試 / 調試困難。盡管松耦合是一項重大的體系結構功能,但是它可以使開發更困難。將兩個對象去耦的情況越多,在查看源代碼或類的關系圖時了解它們之間的依賴性就越難因此,僅當可以安全地忽略兩個對象之間的關聯時才應該將它們松耦合(例如,如果觀察器沒有副作用)。










發表評論

2017怎样手机上赚钱 山西11选5投注网站 浙江6+1体彩开奖结果 开户股票 湖北30选5开奖号码查询 幸运28开奖结果走势图 澳门百家乐注册 11选五5北京玩法规则 吉林11选5一定牛网 新疆11选5推荐号码 上证指数多少点