觀察者(Observer)模式
??? 用途:定義對象之間的一對多依賴關系,因此,當一個對象的狀態發生改變時,其所有依賴項都會得到通知,并自動更新。
??? 它是 OO 設計模式的皇后。該模式被人們廣泛應用(特別是在 GUI 應用程序中),并構成了 MVC 架構的關鍵部分。它處理復雜的問題,而在解決這類問題方面表現得相對較好。但是,從實現需要的努力和代碼理解的角度來說,它還是帶來了一些難以解決的難題。
??? 不足:觀察者(Observer)模式要求您先侵入系統中現有的類,然后才能支持該模式 —— 至少在 Java 語言中是這樣。
??? 而方面可以降低像觀察者(Observer)模式這種侵入性模式的負擔,使得模式參與者更靈活,因為不需要包含模式代碼。而且,模式本身可以變成抽象的基本方面,允許開發人員通過導入和應用它來實現重用,不必每次都要重新考慮模式。
??? 下面通過一個例子來說明:
??? 假設如下的情況:
??? AccountManager 對象能夠觀察 Account,這樣,在帳戶狀態改變時,它們可以向銷售人員發送一封電子郵件。
??? 代碼如下:
public class Account {
??? private int state;
???? private String name;
??? public String getName() {
??????? return name;
??? }
??? public Account(String name) {
??????? super();
??????? this.name = name;
??? }
??? public int getState() {
??????? return state;
??? }
??? public void setState(int state) {
??????? this.state = state;
??? }
???? @Override
??? public String toString() {
??????? return name;
??? }
}
public class AccountManager {
??? public void sendEmail(Account account) {
???????? System.out.println("send Email:" + account);
??? }
}
來看一下java代碼是如何實現觀察者模式的
Java 語言的觀察者雖然實現的差異很明顯,但在它們之間還是有一些相似之處。不論如何實現觀察者,代碼中都必須回答以下 4 個問題:
?? 1. 哪個對象是主體,哪個對象是觀察者?
?? 2. 什么時候主體應當向它的觀察者發送通知?
?? 3. 當接收到通知時,觀察者應該做什么?
?? 4. 觀察關系應當在什么時候開始,什么時候終止?
角色定義??? 首先從標記器接口來分配角色開始。Observer 接口只定義了一個方法:update(),它對應著 Subject 發送通知時執行的操作。 Subject 承擔著更多的職責。它的標記器接口定義了兩個方法,一個用來跟蹤觀察者,另一個用來通知事件的那些觀察者。
public interface Observer {
??? public void update(Subject subject);
}
public interface Subject {? ?
??? public void addObserver(Observer o);
??? public void removeObserver(Observer o);
??? public void notifyObservers();
} ?
一旦定義了這些角色,就可以把它們應用到系統中對應的角色上。
應用觀察者角色
public class AccountManager implements Observer {
?? public void update(Subject subject) {
??????? sendEmail((Account) subject);
??? }
}
跟蹤和通知觀察者一旦這項工作完成,就可以轉移到Subject。在這里,要對 Account進行修改:
? private Set observers = new HashSet(); ?
? public void addObserver(Observer o) {
??? observers.add(o);
? }
? public void removeObserver(Observer o) {
??? observers.remove(o);
? }
? public void notifyObservers() {
??? for (Observer o : observers) {
????? o.update(this);
??? }
? }
觸發事件??? 現在已經把類調整到它們在模式中的角色上了。但是,還需要回過頭來,在對應的事件發生時觸發通知。
??? Account
??? public void setState(int state) {
??????? if (this.state != state) {
??????????? this.state = state;
??????????? notifyObservers();
??????? }
??? }
啟動觀察關系
public class ObserverClient {
??? public static void main(String[] args) {
??????? AccountManager manager = new AccountManager();
??????? AccountManager manager2 = new AccountManager();
??????? Account account = new Account("Account1");
??????? account.addObserver(manager);
??????? account.addObserver(manager2);
??????? account.setState(1);
??? }
}
AspectJ 觀察者定義抽象類來實現觀察者
//采用java5的泛型來定義觀察對象和主體
public abstract class AbstractSubjectObserver<Sub, Obv> {
?????? //不允許空item
??? protected static void iaxIfNull(Object item, String name) {
??????? if (null == item) {
??????????? throw new IllegalArgumentException("null " + name);
??????? }
??? }
?????? //用于保存所有的主體和觀察者之間的對象關系
??? private final HashMap<Sub, ArrayList<Obv>> fObservers = new HashMap<Sub, ArrayList<Obv>>();
??? protected AbstractSubjectObserver() {
??? }
??? public synchronized void addObserver(Sub subject, Obv observer) {
??????? iaxIfNull(subject, "subject");
??????? iaxIfNull(observer, "observer");
??????? getObservers(subject).add(observer);
??? }
??? public synchronized void removeObserver(
??????????? Sub subject,
??????????? Obv observer) {
??????? iaxIfNull(subject, "subject");
??????? iaxIfNull(observer, "observer");
??????? getObservers(subject).remove(observer);
??? }
??? public synchronized ArrayList<Obv> getObservers(Sub subject) {
??????? iaxIfNull(subject, "subject");
??????? ArrayList<Observer> result = fObservers.get(subject);
??????? if (null == result) {
??????????? result = new ArrayList<Observer>();
??????????? fObservers.put(subject, result);
??????? }
??????? return result;
??? }
??? //主體狀態改變,更新所有的觀察者對象
??? protected void subjectChanged(Sub subject) {
??????? iaxIfNull(subject, "subject");
??????? ArrayList<Observer> list = getObservers(subject);
??????? if (!list.isEmpty()) {
??????????? updateObservers(subject, Collections.unmodifiableList(list));
??????? }
??? }
?? //更新所有觀察者操作,調用具體的updateObserver
??? protected synchronized void updateObservers(
??????????? Subject subject,
??????????? List<Observer> observers) {
??????? iaxIfNull(subject, "subject");
??????? iaxIfNull(observers, "observers");
??????? for (Observer observer : observers) {
??????????? updateObserver(subject, observer);
??????? }
??? }
???? //需要子類實現,具體的更新操作
??? protected abstract void updateObserver(Subject subject, Observer observer);
}
定義方面:
public abstract aspect SubjectObserver<Sub, Obv> extends
??????? AbstractSubjectObserver<Sub, Obv> {
??? //需要橫切的代碼,表示哪些需要觸發觀察者模式
??? protected abstract pointcut changing();
??? //在狀態改變后,觸發所有的觀察者
??? after(Sub subject) returning : target(subject) && changing() {
??????? subjectChanged(subject);
??? }
}
無需改動原有的實現,看一下客戶端如何啟動觀察關系
public class ObserverClient {
??? public static void main(String[] args) {
??????? Account account=new Account("Account1");
??????? Client client=Client.aspectOf();
??????? client.addObserver(account,new AccountManager());
??????? client.addObserver(account,new AccountManager());
??????? account.setState(1);
??? }
??? static aspect Client extends SubjectObserver<Account, AccountManager> {
??????? protected pointcut changing() : execution(void? Account.setState(int));
??????? protected void updateObserver(Account account, AccountManager manager) {
??????????? manager.sendEmail(account);
??????? }
??? }
}
AspectJ 觀察者的分析?? 易于理解:從參與者的視角來看,AOP 版本的觀察者更簡單
?? 重用:可以很容易的實現重用
posted on 2006-11-17 16:55
布衣郎 閱讀(1422)
評論(0) 編輯 收藏 所屬分類:
aop