`
beyond429
  • 浏览: 93654 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

用AOP实现观察者模式

阅读更多
观察者(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 版本的观察者更简单
   重用:可以很容易的实现重用
分享到:
评论

相关推荐

    简单的商城项目的实现

    dos运行的商城服务,使用aop、观察者模式,进行对商城的设计,利用低耦合的设计思想。 后台管理系统:管理商品、订单、类目、商品规格属性、用户管理以及内容发布等功能。 前台系统:用户可以在前台系统中进行注册...

    Java EE设计模式:Spring企业级开发最佳实践

    在 Spring 中,观察者模式广泛应用于事件驱动编程中,例如,在 Spring MVC 中,使用观察者模式来处理请求和响应。 4.MVC Pattern:模型视图控制器模式,分离应用程序的关注点,实现高内聚、低耦合的设计。 在 ...

    掌握Spring设计模式:Java工程师必备指南

    代理模式和观察者模式在Spring AOP和事件驱动模型中得到了广泛应用,提供了强大的切面和事件处理能力。策略模式和模板方法模式则分别提供了资源访问的灵活性和统一处理逻辑的框架。最后,责任链模式在Spring的AOP...

    小游戏集合(凑字数1234567)

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    AOP@Work:用AspectJ增强设计模式,第2部分

    本文内容包括:观察者(Observer)模式Java语言的观察者AspectJ观察者AspectJ观察者的分析结束语下载参考资料NicholasLesiecki用这篇深入研究观察者(Observer)模式的文章,继续他对使用面向方面技术实现设计模式的好处...

    【基于java-ssm】大学生兼职论坛管理系统实现源码+lw+部署文档+讲解

    能学到什么:①了解工厂模式、策略模式、观察者模式等在 Spring 框架中的实现方式;②深入理解 IOC、AOP、代理、切面、循环依赖等设计与实现原理。 阅读建议:本资源旨在通过开发简化版 Spring 框架来学习其原理和...

    基于spring+springMvc+mybatis 开发的博客样例

    基于spring+springMvc+mybatis 开发的博客样例,适合具有一定编程基础,比如...能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面,循环依赖都是如何设计和实现的。

    cxxIEG二面1

    介绍SpringIOC/AOP及实现当场去世Spring MVC实现当场去世设计模式单例模式观察者模式工厂模式简单工厂工厂方法抽象工厂不懂Interface &

    Java面试可能问的问题.docx

    观察者模式 装饰模式 3.Spring的优越性 https://blog.csdn.net/hht006158/article/details/80181207 4.SpringMVC注解 @Controller @RestController @RequestMapping @RequestBody @ResponseBody @RequestParam @...

    基于JavaWeb的物业管理系统

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发java web 学习其原理和内核,不仅是代码编写实现也更...

    Apifox-windows-latest

    适合人群:具备一定编程基础,工作1-3年的研发人能学到什么:@工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的: ②IOC, AOP、代理、切面、循环依赖都是如何设计和实现的。阅读建议:此资源以开发简化版Spring...

    期末课设,基于·Android·开发

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    该项目是gradle+springboot+freemarker的项目,是对学生基本信息的增删改查。

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    辉芒微单片机资料和手册,及软件工具

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    Video基础知识简介

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    SSM+课程设计+项目源代码+thymleaf

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也...

    Python版基于pygame的玛丽快跑小游戏源代码,玛丽冒险小游戏代码

    适合人群: 具备一定编程基础,工作1-3年的研发人岗能学到什么: @工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的; 210C、AOP、代理切面、循环依赖都是如何设计和实现的。阅读建议: 此资源以开发简化版...

    maven3.6.3.zip

    适合人群:具备一定编程基础,工作1-3年的研发人能学到什么:@工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的: ②IOC, AOP、代理、切面、循环依赖都是如何设计和实现的。阅读建议:此资源以开发简化版Spring...

    apache-tomcat-8.0.32

    适合人群:具备一定编程基础,工作1-3年的研发人能学到什么:@工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的: ②IOC, AOP、代理、切面、循环依赖都是如何设计和实现的。阅读建议:此资源以开发简化版Spring...

Global site tag (gtag.js) - Google Analytics