观察者(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 版本的观察者更简单
重用:可以很容易的实现重用
分享到:
相关推荐
13. **观察者模式(Observer)**:Spring AOP并没有直接实现观察者模式,但在Spring事件模型中,`ApplicationEventPublisher`和`ApplicationListener`接口体现了观察者模式,允许对象注册监听并响应特定事件。...
观察者模式定义了对象间的一种一对多依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。传统上,这种模式的实现方式是在主题对象的方法中嵌入通知逻辑,这会导致耦合度较高,不易...
5. **代理模式**:Spring AOP通过代理模式实现切面功能,有JDK动态代理和CGLIB代理两种方式,前者针对实现了接口的类,后者则用于未实现接口的类。 通过这个简单的案例,你应该对Spring AOP有了初步的理解。随着...
1. 在Web开发中,Spring框架就广泛应用了设计模式,如工厂模式用于创建Bean,单例模式保证每个Bean只有一个实例,观察者模式用于事件驱动编程,策略模式用于实现AOP(面向切面编程)。 2. 在游戏开发中,状态模式常...
C#的事件和委托系统使得实现如观察者模式变得非常直观。 在C#设计模式(第二版)中,作者可能会深入讨论每种模式的动机、结构、参与者、协作方式以及优缺点。同时,书中还会通过实际的C#代码示例来演示如何在项目中...
行为型模式则关注对象间的职责分配和交互,包括责任链模式、命令模式、解释器模式、迭代器模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。责任链模式定义一系列对象,每个对象处理...
另外,像Guava这样的库,虽然并非直接为设计模式而创建,但它提供的工具类和数据结构可以帮助我们更好地实现一些模式,如Builder模式(通过预定义的构建过程创建复杂对象)和观察者模式(事件驱动的处理方式)。...
Spring AOP(面向切面编程)利用了代理模式,可以为任何对象添加拦截器;而Spring的单例Bean管理,正是单例模式的体现。 总结来说,简单工厂、代理和单例模式是软件设计中的基础工具,它们帮助我们更好地组织代码,...
最后,行为型模式涉及对象之间的责任分配和交互,如策略模式、模板方法模式、观察者模式、职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、状态模式、访问者模式和访问者模式。 在...
本资源"spring_aop1.rar"包含了一个经典的Spring AOP学习案例,是初学者了解和掌握这一特性的好起点。 在Spring AOP中,主要涉及以下几个核心概念: 1. **切面(Aspect)**:切面是关注点的模块化,它封装了横切...
dos运行的商城服务,使用aop、观察者模式,进行对商城的设计,利用低耦合的设计思想。 后台管理系统:管理商品、订单、类目、商品规格属性、用户管理以及内容发布等功能。 前台系统:用户可以在前台系统中进行注册...
2. **观察者模式 (10第十讲观察者模式.7z)** 观察者模式是一种行为设计模式,它定义了对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。在Spring框架中,事件监听...
为了降低这种耦合,开发者开始探索设计模式,例如工厂模式、单例模式和观察者模式等,这些模式提供了一种标准化的方法来解决常见的编程问题。 然而,随着软件系统的复杂度增加,面向方法编程的局限性逐渐显现。比如...
在 Spring 中,观察者模式广泛应用于事件驱动编程中,例如,在 Spring MVC 中,使用观察者模式来处理请求和响应。 4.MVC Pattern:模型视图控制器模式,分离应用程序的关注点,实现高内聚、低耦合的设计。 在 ...
- 请描述一下如何使用观察者模式实现事件驱动编程。 - 何时使用适配器模式?给出一个实际的例子。 - 请解释状态模式,并给出一个实际的应用场景。 - 策略模式如何帮助我们避免硬编码? 5. 面试技巧 - 对每个模式的...
.NET事件系统就是观察者模式的一个实现,如控件的Click事件。 五、装饰器模式 装饰器模式可以在不改变对象原有功能的基础上,动态地给对象添加新的行为。.NET中的委托和事件机制,以及IAsyncResult接口的使用,都...
例如,通过元类(metaclass)可以轻松实现单例模式,装饰器可以用于实现装饰器模式,而面向切面编程(AOP)的概念则可以用于实现观察者模式等。 在"mpdp-code-master"这个压缩包中,你可能会找到每个设计模式的实例...
再者,“行为型”设计模式关注对象之间的交互和责任分配,如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、命令模式(Command)、迭代器模式(Iterator)、备忘录模式(Memento...
7. **观察者模式**: 观察者模式定义了对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。Eclipse的事件监听机制即为此模式的应用。 8. **策略模式**: 策略模式定义...
观察者模式中,一个对象(观察者)关注另一个对象(主题),当主题发生改变时,所有观察者都会得到通知。 通过理解和掌握以上知识点,我们可以更加深入地了解和使用中介者模式的面向方面实现。这种实现方式为处理...