`
YOUNG918
  • 浏览: 184624 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

从Java类库看设计模式(一)

    博客分类:
  • java
阅读更多

作者:刘武东    来自:IBM


在这一部分的内容中,介绍的是一个相对简单但功能强大的模式:Observer模式。希望通过这部分地叙述,大家看了之后,能够对设计模式 有一个比较全面地,感性的认识。

   很多时候,对于一个设计来说(软件上的,建筑上的,或者它他工业上的),经验是至关重要的。好的经验给我们以指导,并节约我们的时间;坏的经验则给我们 以借鉴,可以减少失败的风险。然而,从知识层面上来讲,经验只是作为一种工作的积累而存在于个人的大脑中的,很难被传授或者记录。为了解决这样的问题,人 们提出了所谓的模式的概念。所谓模式,是指在一个特定背景下,反复出现的问题解决方案。模式是经验的文档化。

  软件模式的概念现在比较的 广泛,涉及到分析,设计,体系结构,编码,测试,重构等软件构造生命期中的各个部分。这儿主要讨论的是设计模式,指的是在软件设计过程中反复出现的一些问 题的解决方法了。不过我们一般在提到设计模式的时候,一般都是指GOF的经典书《Design Pattern--Elements of Reusable Object-Oriented Software》出现的23个模式,因而,它是具体的针对于面向对象软件设计过程的。

   从全局上看来,模式代表了一种语言,一种被文档化的经验,甚至是一种文化。往往很多不方便描叙,或者描叙起来很复杂的问题,用模式语言来叙说,会让听者 产生心领神会的感觉。当然,这需要交流双方都能够很好地把握模式语言的含义。然而,这并不是一件容易的事情。模式在各个人的理解上往往存在差异,这篇文章 旨在从一个具体的应用角度:Java类库,来阐叙设计模式。并结合具体的例子,希望能够加深大家对设计模式的理解。

  这儿说的Java类 库,其实并没有局限于JDK本身,还包括了一些其他的类库中的例子,比如JAXP等(当然,下一个版本的JDK中也会包含JAXP了)。其实设计模式的思 想现在应用的如此广泛,无论在什么样的设计中,只要稍微大一点的设计,都可以找到很多很多设计模式的踪迹,或者说都不可避免的用到设计模式。下面所讲的设 计模式,大部分都是GOF的那部经典中出现过的23个模式,然而,还有一些,比如MVC,并不属于那里。一般的来讲,我们认为GOF的23个模式是一些中 级的模式,在它下面还可以抽象出一些更为一般的低层的模式,在其上也可以通过组合来得到一些高级的模式。当然,这儿的低中高的区别,如同区别不同的语言一 样,并没有优劣之分,仅仅是在应用层面上的区别。

  Observer模式

   Observer模式的功用,是希望两个(或多个)对象,我们称之为Subject和Observer,当一方的状态发生改变的时候,另一方能够得到通 知。也就是说,作为Observer的一方,能够监视到Subject的某个特定的状态变化,并为之做出反应。一个简单的例子就是:当一个用户视图中的数 据被用户改变后,后端的数据库能够得到更新,而当数据库被其他方式更新后,用户视图中的数据显示也会随之改变。


图一:Obverser模式的类图

   在JDK中实际上有一个对Observer模式的简单的实现:就是类java.util.Observerable和接口 java.util.Observer。java.util.Observerable类对应于Subject,而java.util.Observer 就是观察者了。JDK中并没有把这两个部分都设计为接口,而是让类java.util.Observerable提供了部分的实现,简化了许多编程的工 作。当然,这也减少了一定的灵活性。

  下面列出了Observer和Observeral的函数列表,及其简单的功能说明

  java.util.Observer:

  public void update(Observable obs, Object obj)
   java.util.Observer 接口很简单,只定义了这一个方法,狭义的按照Observer模式的说法,Observer应该在这个方法中调用Subject的getXXX()方法来 取得最新的状态,而实际上,你可以只是在其中对Subject的某些事件进行响应。这便是Java中的代理事件模型的一个雏形--对事件进行响应。只不 过,在Observer模式中将事件特定化为某个状态/数据的改变了。

  java.util.Observable:

  public void addObserver(Observer obs)
   向Subject注册一个Observer。也就是把这个Observer对象添加到了一个java.util.Observable内部的列表中。在 JDK中对于这个列表是简单的通过一个java.util.Vector类来实现的,而实际上,在一些复杂的Observer模式的应用中,需要把这个部 分单另出来形成一个Manager类,来管理Subject和Observer之间的映射。这样,Subject和Observer进一步的被解藕,程序 也会具有更大的灵活性。

  public void deleteObserver(Observer obs)
  从Subject中删除一个已注册了Observer的引用。

  public void deleteObservers()
  从Subjec中删除所有注册的Observer的引用。

  public int countObservers()
  返回注册在Subject中的Observer个数。

  protected void setChanged()
  设置一个内部的标志以指明这个Ovserver的状态已经发生改变。注意这是一个protected方法,也就是说只能在Observer类和其子类中被调用,而在其它的类中是看不到这个方法的。

  protected void clearChanged()
  清除上叙的内部标志。它在notifyObservers()方法内部被自动的调用,以指明Subject的状态的改变已经传递到Ovserver中了。

public boolean hasChanged()
  确定Subject的状态是否发生了改变。

  public void notifyObservers(Object obj)
   它首先检查那个内部的标志,以判断状态是否改变,如果是的话,它会调用注册在Subject中的每个Observer的update()方法。在JDK 中这个方法内部是作为synchronized来实现的,也就是如果发生多个线程同时争用一个java.util.Observerable的 notifyObservers()方法的话,他们必须按调度的等待着顺序执行。在某些特殊的情况下,这会有一些潜在的问题:可能在等待的过程中,一个刚 刚被加入的Observer会被遗漏没有被通知到,而一个刚刚被删除了的Observer会仍然收到它已经不想要了的通知。

  public void notifyObservers()
  等价于调用了notifyObservers(null)。

   因而在Java中应用Observer就很简单了,需要做的是:让需要被观察的Subject对象继承java.util.Observerable, 让需要观察的对象实现java.util.Observer接口,然后用java.util.Observerable的 addObserver(Observer obj)方法把Observer注册到Subject对象中。这已经完成了大部分的工作了。然后调用java.util.Observerable的 notifyObservers(Object arg)等方法,就可以实现Observer模式的机理。我们来看一个简单使用了这个模式的例子。这个例子有三个 类:FrameSubject,DateSubject,FrameObject和EntryClass,FrameSubject中用户可以设置被观察 的值,然后自动的会在FrameObject中显示出来,DateSubject封装被观察的值,并且充当Observer模式中的Subject。

public class FrameSubject extends JFrame {
…………
  //因为无法使用多重继承,这儿就只能使用对象组合的方式来引入一个
//java.util.Observerable对象了。
  DateSubject subject=new DateSubject();

 //这个方法转发添加Observer消息到DateSubject。
  public void registerObserver(java.util.Observer  o){
    subject.addObserver(o);
 }

  //数据改变,事件被触发后调用notifyObservers()来通知Observer。
void jButton1_actionPerformed(ActionEvent e) {
    subject.setWidthInfo(Integer.parseInt(jTextField1.getText()));
    subject.setHeightInfo(Integer.parseInt(jTextField2.getText()));
    subject.notifyObservers();
  }
……………
}

public class DateSubject extends Observable {

    //封装被观察的数据
  private int widthInfo;
  private int heightInfo;

  public int getWidthInfo() {
    return widthInfo;
  }

  public void setWidthInfo(int widthInfo) {
this.widthInfo = widthInfo;
//数据改变后,setChanged()必须被调用,否则notifyObservers()方法会不起作用
this.setChanged();
  }
  public void setHeightInfo(int heightInfo) {
    this.heightInfo = heightInfo;
    this.setChanged();
  }
  public int getHeightInfo() {
    return heightInfo;
  }
}

public class FrameObserver extends JFrame implements java.util.Observer {
…………
    //观察的数据
   int widthInfo=0;
   int heightInfo=0;

//在update()方法中实现对数据的更新和其它必要的反应。
  public void update(Observable o, Object arg) {
    DateSubject subject=(DateSubject) o;
    widthInfo=subject.getWidthInfo();
    heightInfo=subject.getHeightInfo();
    jLabel1.setText("The heightInfo from subject is:  ");
    jLabel3.setText(String.valueOf(heightInfo));
    jLabel2.setText("The widthInfo from subject is:  ");
    jLabel4.setText(String.valueOf(widthInfo));
  }
……………
}

public class EntryClass {
    public static void main(String[] args) {
    ……………
    FrameSubject frame = new FrameSubject();
FrameObserver frame2=new FrameObserver();
//在Subject中注册Observer,将两者联系在一起
frame.registerObserver(frame2);
…………
frame.setVisible(true);
frame2.setVisible(true);

    ……………
    }
}

   我认为在JDK中这个Observer模式的实现,对于一般的Observer模式的应用,已经是非常的足够了的。但是一方面它用一个类来实现了 Subject,另一方面它使用Vector来保存Subject对于Observer的引用,这虽然简化了编程的过程,但会限制它在一些需要更为灵活, 复杂的设计中的应用,有时候(虽然这种情况不多),我们还不得不重新编写新的Subject对象和额外的Manager对象来实现更为复杂的 Observer模式的应用。

  小结:

  这一部分主要的讨论了模式的概念。随着现代 软件工业的不断进步,软件系统的规模的日益扩大,越来越需要对某些个不断出现的问题进行模式化思维,以成功的经验或者失败的教训来减少软件开发失败的风 险。模式代表了一种文档化的经验,它为某一类的问题提供了最好(或者说很好)的解决方案,使得即使不是经验丰富的软件工程师,也能够根据模式来构建相对成 功的系统。本节给出的一个Obverser模式的示例,比较好的说明了这一点。Obverser模式主要解决在对象间的状态映射或者镜像的问题。

 

  参考资源:

  • Software Patterns: James O. Coplien, Bell Laboratories,The Hillside Group
  • 设计模式:可复用面向对象软件的基础 机械工业出版社
  • Java2类库增补版 机械工业出版社
  • 可视化面向对象建模技术 北京航天航空工业大学出版社
  • JDK1.3源代码
  • UML用户指南 机械工业出版社

 

分享到:
评论

相关推荐

    从Java类库看设计模式

    从Java类库看设计模式

    从Java类库看设计模式.pdf

    从Java类库看设计模式.pdf

    设计模式+UML.rar

    包含以下文件: Java设计模式-图解-附代码.pdf 从Java类库看设计模式.doc 六大UML类图关系.docx 认识UML类图元素_java之UML.doc 设计模式6大原则.doc 设计模式学习笔记.doc 深入浅出设计模式(中文版).pdf

    java设计模式-状态

    java,设计模式中的一种,状态设计模式。

    Java设计模式

    设计模式贯穿于整个Java体系,我们所用的大小型框架和Java本身类库里面都用了大量的设计模式。初学者有些地方不懂没关系,知道有这回事就行了,背下每一种设计模式结构的角色(UML类图),随着你平时本身学习Java的...

    基于设计模式的Java swing交互式界面模式的应用研究与实现

    交互式用户界面模型的特点,提出了一种基于java/swing和两种设计模式的交互 式界面的设计思想与具体实现方案。该方案包含用户界面代理,能提供给用户图 形的可视化方式来设计界面的视图,和控制器的设计;这套方案...

    java类库源码-java-interceptor:库,使“Interceptor”设计模式可用于“普通的Java对象”方法。它使用自定义类加

    java 类库 源码

    java面向对象编程源码

    本书内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化 Java编程的各种宝贵经验,深入阐述Java虚拟机执行Java程序的原理。...

    Java容器学习笔记:容器概览,容器中的设计模式,容器源码分析 - List,容器源码分析 - Map,容器源码分析 - 并发容

    容器中的设计模式, 容器源码分析 - List, 容器源码分析 - Map, 容器源码分析 - 并发容 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,意味着可以在不同的操作系统上...

    java学习:01.设计模式.md

    Java是一种高级的面向对象的程序设计语言,它具有广泛的应用和强大的跨平台特性。Java语言于1995年由Sun公司推出,由Java之父詹姆斯高斯林设计。Java的设计目标是提供一种易学易用、功能强大的编程语言,使开发人员...

    java源码包---java 源码 大量 实例

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    设计模式之迭代器模式

    设计模式 java 迭代器模式

    JAVA上百实例源码以及开源项目

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    Java 面向对象编程.pdf

    《Java 面向对象编程》内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化Java编程的各种宝贵经验,深入阐述Java虚拟机执行...

    JAVA上百实例源码以及开源项目源代码

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    Java源码包100个设计实例.zip

    JAVA短信网关平台(值得一看).rar Java绘制图片火焰效果.rar Java编写的HTML浏览器.rar Java编写的山寨QQ,多人聊天+用户在线.rar Java编写的显示器显示模式检测程序.rar Java编写的网页版魔方游戏.rar java聊天室 ...

    JAVA面向对象编程(孙卫琴).z01

    本书内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化Java编程的各种宝贵经验,深入阐述Java虚拟机执行Java程序的原理。...

Global site tag (gtag.js) - Google Analytics