动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息



本月文章推荐
.FreeJava 的使用方法.
.JBuilder2005创建开发文档之Java.
.RuntimeException的特殊情况.
.深入理解abstract class和i.
.T.class的获取和为擦拭法站台.
.Java与正则表达式(2年级2).
.JAVA程序员面试32问,你能回答多少.
.Java学习:线程池的简单构建.
.给 Java SE 注入脚本语言的活力.
.如何在Java中实现远程方法调用.
.利用缓存机制快速读取XML文件数据.
.基于服务器的Java安全产品.
.关于在Java Web中的入侵检测及简.
.J2SE1.5新特性之使用代理服务器.
.保持你对Java的敏感度.
.对象的创建和存在时间.
.Eclipse下实现软件项目的源码管理.
.Java中文问题详解(推荐).
.《Java 手机/PDA 程序设计入门》.
.在Java开源的王国中自由翱翔.

观察者模式组图(Observer Pattern)

发表日期:2008-1-5 |



  描述:
  
  在设计一组依靠的对象与它们所依靠的对象之间一致(同步)的交流模型时,观察者模式(Observer Pattern)很有用。它可以使依靠对象的状态与它们所依靠的对象的状态保持同步。这组依靠的对象指的是观察者(Observer),它们所依靠的对象称为主题(Subject)。为了实现观察者(Observer)的状态与主题(Subject)保持同步,观察者模式(Observer Pattern)
  
  推荐采用发布者--订阅者(publisher--subscriber)模型,以使这组观察者(Observer)和主题(Subject)对象之间有清楚的界限。
  
  典型的观察者(Observer)是一个依靠于或者关注于主题对象的状态的对象。一个主题可以有一个或者多个观察者。这些观察者在主体的状态发生变化时,需要得到通知。
  
  由于给定主体的观察者链表需要动态的变化,因此一个主题不能维护一个静态的观察者链表。因此关注于主题状态的任何对象都需要明确地注册自己为主体的一个观察者。主题状态发生的变化,都需要通知所有的以注册的观察者。从主题接到通知以后,每一个观察者查询主题,使自己的状态与主题的同步。因此一个主题扮演着发布者的角色,发布信息到所有的以订阅的观察者。
  
  换句话说,主题和它的观察者之间包含了一对多的关系。当主题的实例的状态发生变化时,所有的依靠于它的观察者都会得到通知并更新自己。每一个观察者对象需要向主题注册,当主题的状态发生变化的时候得到通知。一个观察者可以注册或者订阅多个主题。当观察者不希望再得到通知时,它可以向主题进行注销。
  
  为了实现这种机制:
  
  (1)  主题需要为注册和注销通知提供一个接口。
  
  (2)  下面的两点也需要满足:
  
  A、  拉模型(In the pull model)--主题需要提供一个接口,可以使观察者查询主题获得需要的状态信息来更新自己的状态。
  
  B、  推模型(In the push model)--主题发送观察者可能关注的状态信息。
  
  (3)  观察者需要提供一个可以从主题接受通知的接口。
  
  类图(图33.1)描述了为满足于以上需求,不同类的结构和它们之间的关联关系。
  
 观察者模式组图(Observer Pattern)(图一)
  Figure 33.1: Generic Class Association When the Observer Pattern Is Applied
  

  从这个类图可以看到:
  
  (1)  所有的主题需要提供一个类似于Observable接口的实现。
  
  (2)  所有的观察者需要提供一个类似于Observer接口的实现。
  
  在应用观察者模式时,有几种变体。这就会产生不同类型的主题--观察者模式,例如,观察者仅关注主体特定类型的变化等。
  
  增加新的观察者:
  
  应用观察者模式以后,在不影响主题类的情况下,可以动态的加入不同的观察者。同样,主题的状态变化逻辑改变时,观察者也不会受到影响。
  
  例子:
  
  为了治理一个卖厂多个分类产品,让我们建立一个销售报表系统。这个系统有以下特征:
  
  (1)  用户可以选择一个他们感爱好的分类
  
  (2)  在选择了一个分类以后,需要显示下面的两种类型的报表。
  
  A、  月度报表(Monthly report)--所选分类当月的所有交易清单。
  
  B、  年度累积额(YTD sales chart)--以月为单位显示选择分类的年度累积额图。
  
  (3)  当一个不同的分类被选择时,两种报表的数据会被刷新,显示当前所选分类的报表。
  
  为了实现以上期望的功能,我们很轻易的看到两个报表对象依靠于持有用户选择分类的对象。应用观察者模式于此场景,我们可以设计一个介于持有用户选择分类的对象和两个报表对象之间一个一致(同步)的交流模型。
  
  让我们定义三个类,它们的功能如表33.1所描述:
  
  Table 33.1: Subject-Observer Classes
  public interface Observable {
  public void notifyObservers();
  public void register(Observer obs);
  public void unRegister(Observer obs);
  }
  
  ReportManager类(Listing33.1)提供了声明在Observable接口中方法的实现。两个依靠于ReportManager的报表对象使用这些方法注册它们自己为观察者。ReportManager把这些注册的观察者保存到observersList矢量(vector)中。当前选择的分类构成了ReportManager对象的状态,它以实例变量的形式保存在变量department中。当为department设置一个新的值时(也就是ReportManager对象的状态改变),notifyObservers方法被调用。作为notifyObservers方法的一部分,ReportManager调用注册为观察者的refreshData(Observable)方法。
  Listing 33.1: ReportManager Class
  
  public class ReportManager extends JFrame
  implements Observable {
  …
  …
  private Vector observersList;
  private String department;
  public ReportManager() throws Exception {
  …
  …
  observersList = new Vector();
  …
  …
  }
  public void register(Observer obs) {
  //Add to the list of Observers
  observersList.addElement(obs);
  }
  public void unRegister(Observer obs) {
  //remove from the list of Observers
  }
  public void notifyObservers() {
  //Send notify to all Observers
  for (int i = 0; i < observersList.size(); i++) {
  Observer observer =
  (Observer) observersList.elementAt(i);
  observer.refreshData(this);
  }
  }
  public String getDepartment() {
  return department;
  }
  public void setDepartment(String dept) {
  department = dept;
  }
  class ButtonHandler implements ActionListener {
  ReportManager subject;
  public void actionPerformed(ActionEvent e) {
  if (e.getActionCommand().equals(ReportManager.EXIT)) {
  System.exit(1);
  }
  if (e.getActionCommand().equals(ReportManager.SET_OK)) {
  String dept = (String)
  cmbDepartmentList.getSelectedItem();
  //change in state
  subject.setDepartment(dept);
  subject.notifyObservers();
  }
  }
  public ButtonHandler() {
  }
  public ButtonHandler(ReportManager manager) {
  subject = manager;
  }
  }
  }//end of class
  
  除了提供Observable接口方法的实现,ReportManager还显示了必要的用户接口,答应用户选择一个特定的、关注的分类。
  
  让我们定义接口Observer的两个实现:MonthlyReport和YTDChart类
  
  public interface Observer {
  public void refreshData(Observable subject);
  }
  
 观察者模式组图(Observer Pattern)(图二)
  Figure 33.2: Observer Class Hierarchy
  

  Listing 33.2: MonthlyReport Class as an Observer
  
  public class MonthlyReport extends JFrame implements Observer {
  …
  …
  private ReportManager objReportManager;
  public MonthlyReport(ReportManager inp_objReportManager)
  throws Exception {
  super("Observer Pattern -- Example");
  objReportManager = inp_objReportManager;
  //Create controls
  …
  …
  //Create Labels
  …
  …
  objReportManager.register(this);
  }
  public void refreshData(Observable subject) {
  if (subject == objReportManager) {
  //get subject's state
  String department = objReportManager.getDepartment();
  lblTransactions.setText(
  "Current Month Transactions - " +
  department);
  Vector trnList =
  getCurrentMonthTransactions(department);
  String content = "";
  for (int i = 0; i < trnList.size(); i++) {
  content = content +
  trnList.elementAt(i).toString() + "\n";
  }
  taTransactions.setText(content);
  }
  }
  private Vector getCurrentMonthTransactions(String department
  ) {
  Vector v = new Vector();
  FileUtil futil = new FileUtil();
  Vector allRows = futil.fileToVector("Transactions.date");
  //current month
  Calendar cal = Calendar.getInstance();
  cal.setTime(new Date());
  int month = cal.get(Calendar.MONTH) + 1;
  String searchStr = department + "," + month + ",";
  int j = 1;
  for (int i = 0; i < allRows.size(); i++) {
  String str = (String) allRows.elementAt(i);
  if (str.indexOf(searchStr) > ?1) {
  StringTokenizer st =
  new StringTokenizer(str, ",");
  st.nextToken();//bypass the department
  str = " " + j + ". " + st.nextToken() + "/" +
  st.nextToken() + "~~~" +
  st.nextToken() + "Items" + "~~~" +
  st.nextToken() + " Dollars";
  j++;
  v.addElement(str);
  }
  }
  return v;
  }
  }//end of class
  
  ReportManager利用这个接口通知它的所有观察者。
  
  主题--观察者的关联(Subject--Observer Association)
  
  通常,一个客户首先需要创建一个主题(ReportManager)实例,当一个观察者(例如:MonthlyReport,YTDChart)对象被创建。客户把主题ReportManager实例的引用传递给观察者的构造函数,观察者将自身注册到当前主题实例上。
  
  //Client Code
  public class SupervisorView {
  …
  …
  public static void main(String[] args) throws Exception {
  //Create the Subject
  ReportManager objSubject = new ReportManager();
  //Create Observers
  new MonthlyReport(objSubject);
  new YTDChart(objSubject);
  }
  }//end of class
  
  类之间的关联描述如下:
  
 观察者模式组图(Observer Pattern)(图三)
  Figure 33.3: Example Application--Class Association
  

  逻辑流程:
  
  (1)  使用ReportManager用户接口,当用户选择一个特定的分类并且点击OK按钮时,ReportManager的内部状态被被改变(例如,ReportManager实例变量department的值发生改变)。
  
  (2)  新的状态一旦被设置,ReportManager调用两个注册的观察者MonthlyReport和YTDChart的refreshData(Observable)方法。
  
  (3)  作为refreshData方法的一部分,两个report对象需要:
  
  A、  检查以确保调用refreshData方法的主题和观察者这册的主题是同一个主题。这就避免了观察者响应不必要的调用。
  
  B、  使用getDepartment方法查询ReportManager的当前状态。
  
  C、  从数据文件中提取响应的数据显示。
  
 观察者模式组图(Observer Pattern)(图四)
  Figure 33.4: MonthlyReport View

  
  当ReportManager的状态变化逻辑实现需要改变时,任何观察者不受影响。同样,当一个新的观察者被加入时,ReportManager类不需要任何变化。
上一篇:Java I/O 包中的Decorator模式介绍 人气:320
下一篇:备忘录模式(Memento Pattern) 人气:369
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-7-24 Sablog-X v2.0 预览版
2008-7-24 帝国备份王EmpireBak 2008 正式版
2008-7-24 网趣网上购物系统时尚版 v8.2
2008-7-24 纵横B2B电子商务系统XYECS!B2B v
2008-7-24 e路小说小偷 v1.2.0723
2008-7-24 凌风美女图片站程序 v2.2
2008-7-24 TOM15电影收索程序
2008-7-24 清风信息自动采集生成系统 v1.0
2008-7-24 QQ邮箱编辑器 v1.0 (小小菜刀ASP
2008-7-19 UltraEdit 简体中文增强版 14.10
2008-7-19 CentOS 5.2 i386 LiveCD
2008-7-19 Snapture多功能相机 v1.4
2008-7-19 iAcces中文输入法 v1.0Build016
2008-7-19 Cookbook烹饪秘籍 v2.5
2008-7-19 苹果专用DVD转换工具 v1.1.59汉化
2008-7-19 Modem修复软件ZiPhone修改版04.0
2008-7-19 AgileMessenger即时通讯工具美化
2008-7-19 Sketches画图软件 v0.7b6破解版


  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号