文档章节

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

FansUnion
 FansUnion
发布于 2015/10/22 10:30
字数 1266
阅读 2
收藏 0
点赞 0
评论 0
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);
 }

 }

图片

版权声明:本文为博主原创文章,未经博主允许不得转载。

© 著作权归作者所有

共有 人打赏支持
FansUnion
粉丝 56
博文 857
码字总数 825464
作品 0
丰台
高级程序员

暂无相关文章

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

聊聊spring cloud的RequestRateLimiterGatewayFilter

序 本文主要研究一下spring cloud的RequestRateLimiterGatewayFilter GatewayAutoConfiguration @Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMi......

go4it ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部