本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7594388
建立时间:2006年5月29日




[设计模式]用AOP实现观察者模式
软件技术

lhwork 发表于 2006/12/30 10:07:14

观察者(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 版本的观察者更简单   重用:可以很容易的实现重用


阅读全文(3623) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.500 second(s), page refreshed 144773420 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号