`
FansUnion
  • 浏览: 154448 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

事件响应机制与观察者模式

 
阅读更多
GUI事件处理和程序中使用接口回调

这种一次性注册回调程序的方式允许由运行时系统在需要回调某个事件处理程序时做出初步的决定,而不是由处理程序决定。

下面通过代码分步骤详细解释这一过程:

1.运行时库定义了一个接口,其中承诺有一个itHappened()方法。

示例如下:

Public interfaceActionListener{

Public void itHappened();

}

运行时系统将会调用接口承诺的上述方法。

2.处理程序代码将实现这一接口。

因此,我们将在自己的程序代码中提供了一个实现了上述接口的类:

ClassMyActionListener implements ActionListener{

Public voidinHappened(){

//…

}

}

这就是我们的一个事件处理程序。

3.在我们的应用程序代码中,一次性地调用运行时库,注册自己感兴趣的点击按钮等事件,并告之事件处理程序。

MyActionListenerlistener = new MyActionListener();

Runtime.registerActionListener(listener);

4.在运行时系统中,注册例程将保存对任何注册对象的引用。

PrivateActionListener[] registeredObjects;

registerActionListener(ActionListenerlistener){

registerObjects[i] = listener;

}

5.这一步时前面所有步骤的最终目的。

无论何时运行时系统检查发现一个GUI事件出现,它将回调任何已经注册为处理相应事件的itHappened()方法:

For(ActionListenerlistener:registerObjects){

Listener.itHappened();

}

当事件发生时,可能需要通知一系列已经注册到运行时系统的ActionListener,但经常只有一个时正确的。

这就是GUI事件处理程序的工作原理。其中关键的一点是第5步的代码需要在一个单独的线程中运行,使之能够在任何时刻反向调用ActionListener,因而称为回调(CallBack)。

事件响应机制实际上就使用了观察者模式,以下是一个观察者模式的具体例子。

public abstract class Subject {

private boolean changed = false;
private Vector obs;

public Subject() {
obs = new Vector();
}

public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}

public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}

public void notifyObservers() {
notifyObservers(null);
}

public void notifyObservers(Subject arg) {

Object[] arrLocal;

synchronized (this) {

if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}

for (int i = arrLocal.length - 1; i >= 0; i--)
((Observer) arrLocal[i]).update(this, arg);
}

public synchronized void deleteObservers() {
obs.removeAllElements();
}

protected synchronized void setChanged() {
changed = true;
}

protected synchronized void clearChanged() {
changed = false;
}

public synchronized boolean hasChanged() {
return changed;
}

public synchronized int countObservers() {
return obs.size();
}
}

package org.leiwen.dp.action.observer;

public class Book extends Subject {

private String name;

private double price;

// 更新书籍信息,调用该方法
public void update(Book book) {
if (book == null) {
return;
}

boolean isSame = name.equals(book.getName())
&& (price == book.getPrice());
if (!isSame) {
setChanged();
}
// 通知客户书已经更新
notifyObservers(book);

}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}

}

package org.leiwen.dp.action.observer;

public class Mouse extends Subject {
private String name;

private double price;

// 更新鼠标信息,调用该方法
public void update(Mouse mouse) {
if (mouse == null) {
return;
}

boolean isSame = name.equals(mouse.getName())
&& (price == mouse.getPrice());
if (!isSame) {
setChanged();
}
// 通知客户鼠标已经更新
notifyObservers(mouse);

}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}

}

package org.leiwen.dp.action.observer;

public interface Observer {

// 参数个数和类型可以自定义
void update(Subject o, Subject arg);
}

package org.leiwen.dp.action.observer;

//观察者
public class BuyerEmail implements Observer {

// 该方法会被“被观察者的父类”即Observable调用
@Override
public void update(Subject subject, Subject arg) {
//更新算法多种多样,根据实际情况而定
// 这里是具体的发电子邮件的程序
System.out.println("邮件收到的消息:"
+ ObserverUtil.getNotifyMessage(subject, arg));
}

}

package org.leiwen.dp.action.observer;

//观察者
public class BuyerMobile implements Observer {

// 该方法会被“被观察者的父类”即Subject调用
@Override
public void update(Subject subject, Subject arg) {
// 这里是具体的发手机短信的程序
System.out.println("手机收到的消息:"
+ ObserverUtil.getNotifyMessage(subject, arg));

}
}

package org.leiwen.dp.action.observer;

public abstract class ObserverUtil {

// 工具类,根据书原有的信息和新的信息,构造向用户发送的消息内容。
public static String getNotifyMessage(Subject subject, Subject arg) {
// 具体构造算法,需要根据实际情况而定
String message = "";

if (subject instanceof Book && arg instanceof Book) {

Book oldBook = (Book) subject;
Book newBook = (Book) arg;

double diff = newBook.getPrice() - oldBook.getPrice();
if (diff < 0) {
message = "亲爱的Fans,<<" + newBook.getName() + ">>降价"
+ Math.abs(diff) + "元! 快来购买吧!";
}
} else if (subject instanceof Mouse && arg instanceof Mouse) {

Mouse oldMouse = (Mouse) subject;
Mouse newMouse = (Mouse) arg;

double diff = newMouse.getPrice() - oldMouse.getPrice();
if (diff < 0) {
message = "亲爱的Fans," + newMouse.getName() + "降价"
+ Math.abs(diff) + "元! 快来购买吧!";
}
}
return message;

}
}

package org.leiwen.dp.action.observer;

public class ObserverTest {

public static void main(String[] args) {
// ------------------第1个测试例子-----------------------------
// 主题,被观察者
Book book = new Book();
book.setName("Struts2技术内幕");
book.setPrice(45.3);

// 下面的观察者在实际应用中可以从数据库或文件中读取
BuyerEmail be = new BuyerEmail();
BuyerMobile bm = new BuyerMobile();

// 增加观察者,在实际应用中就是哪些人对该书作了关注
book.addObserver(be);
book.addObserver(bm);

Book updatedBook = new Book();
updatedBook.setName(book.getName());
updatedBook.setPrice(book.getPrice() - 3);
book.update(updatedBook);

// ------------------第2个测试例子-----------------------------
// 主题,被观察者
Mouse mouse = new Mouse();
mouse.setName("雷柏3100P鼠标");
mouse.setPrice(55.6);

// 下面的观察者在实际应用中可以从数据库或文件中读取
BuyerEmail be2 = new BuyerEmail();
BuyerMobile bm2 = new BuyerMobile();

// 增加观察者,在实际应用中就是哪些人对该鼠标作了关注
mouse.addObserver(be2);
mouse.addObserver(bm2);

Mouse updatedMouse = new Mouse();
updatedMouse.setName(mouse.getName());
updatedMouse.setPrice(mouse.getPrice() - 5);
mouse.update(updatedMouse);
}

}

图片

分享到:
评论

相关推荐

    观察者模式(Observer)原理图

    观察者模式(Observer Pattern)是一种对象行为型设计模式,它定义了对象之间的一对多依赖关系。 当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常用于实现分布式事件处理系统...

    深入探索Spring事件监听机制:技术与应用

    这种机制基于观察者模式,由事件(ApplicationEvent)、事件监听器(ApplicationListener)和事件广播器(ApplicationEventMulticaster)三个主要组成部分构成。 事件是发生的动作或事情,其核心是ApplicationEvent...

    Vue源码学习 — 响应式原理之观察者模式

    1. 观察者模式 概念 观察者模式又被称为 发布-订阅 模式,这种模式定义了对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并完成自动更新。 优点 观察者与被观察者是...

    软件开发专业前端开发专门用作面试的vue面试题

    vue 中使用了哪些设计模式?...4、观察者模式。(响应式数据原理) 5、装饰器模式(@装饰器的用法) 6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案 - 比如选项的合并策略。

    函数响应式编程库ReactiveSwift.zip

    ReactiveSwift 是出自 ReactiveCocoa 小组的纯 Swift 风格 FRP。 ReactiveSwift 提供了可组合、可声明以及灵活的原语,建立在时间流的大概念之下。这些原语可用于统一展现通用 Cocoa ...FRP非常类似于GOF的观察者模式。

    实现基于Vue3组合式API的登陆系统

    在很多公司的前端框架使用中,Vue做为一门技术流行开来,具备了虚拟DOM树,面向组件的开发模式和观察者模式等优点。nodejs是JavaScript的一个运行环境,使得我们在前端写的js代码能够在服务端运行。相较于传统的web...

    apple MVC 架构

    (比较:观察者模式(软件设计模式)) 视图(View)能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),...

    android 网络应用轻量框架-多线程管理-高效缓存-设计模式

    6:使用状态模式 观察者模式更好的处理多线程 最初的想法:网络优化开发框架 (移除任务未完成) 网络稳定,系统运行稳定性,大内存消耗稳定,长时间运行稳定性 (旧的系统症结所在) 开启过多线程,导致系统...

    Reactive Extensions for [removed]用于可观察流的异步编程的API-开源

    观察者模式做得正确。 ReactiveX是来自最佳创意的组合。 观察者模式,迭代器模式和功能编程。 ReactiveX无处不在,它适用于一切。 适用于惯用的Java,Scala,C#,C ++,Clojure,JavaScript,Python,Groovy,...

    asp.net知识库

    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable 与DotNet数据对象结合的自定义数据对象设计 (一) 数据对象与DataRow ASP.NET中大结果集的分页[翻译] .net 2.0 访问Oracle --与Sql Server的...

    《Android应用开发》个人总结报告.doc

    局模式可以在比较简单的include进行完成,最重要的一点就是:我们可以自己通过重写 方法或者通过实现View或者Layout等类进行扩充项目需 要的布局(或者控件) ,在学习界面中,我发现Android为我们提供了很好的类似反射...

    Java并发编程(学习笔记).xmind

    生产者-消费者模式 中断的处理策略 传递InterruptedException 恢复中断,让更高层的代码处理 PriorityQueue(非并发) ConcurrentSkipListMap 替代同步的SortedMap ...

    java 面试题 总结

    Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来...

    超级有影响力霸气的Java面试题大全文档

     Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常...

    Python编程入门经典

    4.5 观察多个比较运算的结果 54 4.6 循环 57 4.6.1 重复执行操作 57 4.6.2 终止循环 59 4.7 处理错误 62 4.8 本章小结 64 4.9 习题 65 第5章 函数 67 5.1 将程序放在单独的文件中 67 5.2 函数:在一个名称下聚集 ...

    windows 程序设计

    在早期,视讯显示器仅用于响应使用者通过键盘输入的文字。在图形使用者接口中,视讯显示器自身成为使用者输入的一个来源。视讯显示器以图标和输入设备(例如按钮和滚动条)的形式显示多种图形对象。使用者可以使用...

    深入解析Windows操作系统中文.part2.rar

    检查与进程、线程和作业相关的数据结构和算法;观察Windows如何管理虚拟内存和物理内存;理解NTFS的操作和格式,诊断文件系统访问问题;从上往下查看Windows的网络栈,包括映射、API、名称解析和协议驱动程序;诊断...

    ORACLE9i_优化设计与系统调整

    §5.1.1 响应时间与吞吐量的折衷 82 §5.1.2 临界资源 83 §5.1.3 过度请求的影响 83 §5.1.4 调整以解决问题 83 §5.2 优化的执行者 84 §5.3 设置性能目标 84 第7章 系统优化方法 85 §6.1 何时优化效率最高 85 §...

    软件设计规范

    工业控制也开启了新的软件世界,因为软件要从分离的输入建立“综合感知”,感知到设备状态,然后做出响应。 软件有其固有的物理属性,也就是计算的量。算法领域,无论算法的论证多么曲折,求得的结果,物化为软件,...

Global site tag (gtag.js) - Google Analytics