详解Java编程的Observer观察者设计模式

作者:Willis Yang 时间:2023-11-10 04:06:07 

 java语言里包含了许多对设计模式的直接支持,如command模式,agent模式,observer模式等。虽然java提供的对这些模式的支持很简单,不能满足比较复杂的应用。但在简单的场景下,使用这些类往往能够得到立杆见影的效果。所以,如果没有什么特殊需求,还是最好利用java的这些类。
        Observer模式,又称监听模式,观察者模式,是经典设计模式之一(one of GOF)。java语言中,对这种模式支持的类和接口主要有以下几个,全部来自java.beans包:


java.beans.PropertyChangeListener (interface)
java.beans.PropertyChangeSupport (class)
java.beans.PropertyChangeEvent (class)
java.beans.PropertyChangeListener

      这是一个接口,很显然,所有实现这个接口的类就是listener啦(或者叫observer),它会对被监听的对象的某些变化感兴趣。这个接口就一个方法:


public void propertyChange(PropertyChangeEvent evt) {  
// TODO Auto-generated method stub  
}

接口定义很简单,作用也很明显。接受一个event(被监听者产生的PropertyChangeEvent),然后根据这个event做点反应。


java.beans.PropertyChangeSupport

         这个类用在被观察者的类里,用来保存注册的观察者,并负责向他们提供被观察者的变化信息。这个类的方法也不多,不过还是只介绍100%用到的,要不脑子就不够使了,呵呵。


public PropertyChangeSupport(Object sourceBean)

      这是构造函数,参数就是被监听者。PropertyChangeListener一般作为被监听者的一个属性。一般如下使用:


private PropertyChangeSupport listeners = new PropertyChangeSupport(this);

 
      注意,这个listeners可不是只代表一个监听者,他可能是一群监听者。那么如何这些listeners是谁呢?这回用到下面的方法了。


public void addPropertyChangeListener(PropertyChangeListener listener)

        这个类太容易了,把监听者加进来。就像开 * 一样,记者想要采访,就得先登记一下。显然这个方法可以多次调用(add嘛)。有加就有减:


public void removePropertyChangeListener(PropertyChangeListener listener)

如果这个监听者对被监听者的任何变化多不感兴趣了,就被被监听者赶了出去。
好了,记者都到齐了,被监听者有变化了就该通知人家了,使用如下方法的一个:


public void firePropertyChange(PropertyChangeEvent evt)  

public void firePropertyChange(String propertyName,  
               boolean oldValue,  
               boolean newValue)  

public void firePropertyChange(String propertyName,  
               int oldValue,  
               int newValue)  

public void firePropertyChange(String propertyName,  
               Object oldValue,  
               Object newValue)

实际上,后三个方法的参数都会封装成PropertyChangeEvent,然后调用第一个方法。不过在实际中,我们还是喜欢直接调用后三个中的一个,封装的事我们就不管了。后三个方法的参数都是三个,其中的oldValue和newValue就是改变前后的值,第一个就是给改变一个名字,好让监听者们根据这个名子来做响应。就像开会,政府的所有信息都会被记者听到,但是有的记者只对台湾问题感兴趣,而有的记者对中日问题感兴趣。
对PropertyChangeSupport方法的介绍就这么多吧。注意,PropertyChangeSupport既然被用到了被观察者的类(一般是一个model)里,那么他的这些方法就只在被观察这里调用。


java.beans.PropertyChangeEvent

       这个类我也懒得介绍,看看他的主要方法就明白怎么回事了


public String getPropertyName()  
public Object getNewValue()  
public Object getOldValue()

就者三个类,再有就是具体问题具体分析了。来个例子吧,首先是被观察者:


public class Domain{  
 protected String id;  
 protected String name;  
 protected String desName;  

protected PropertyChangeSupport listeners = new PropertyChangeSupport(this);  

public String getId() {  
   return id;  
 }  

public void setId(String id) {  
   this.id = id;  
   firePropertyChange("Domain.id", null, id);  
 }  

public String getDesName() {  
   return desName;  
 }  

public void setDesName(String desName) {  
   this.desName = desName;  
   firePropertyChange("Domain.desName", null, desName);  
 }  

public String getName() {  
   return name;  
 }  

public void setName(String name) {  
   this.name = name;  
   firePropertyChange("Domain.name", null, name);  
 }  

public void addPropertyChangeListener(PropertyChangeListener listener) {  
   listeners.addPropertyChangeListener(listener);  
 }  

public void firePropertyChange(String propName, Object oldValue, Object newValue) {  
   listeners.firePropertyChange(propName, oldValue, newValue);  
 }  

public void removePropertyChangeListener(PropertyChangeListener listener) {  
   listeners.removePropertyChangeListener(listener);  
 }  
}

有人对Domain的三个属性感兴趣。下面就是这些人中的一个:


public class SimpleObserver implements PropertyChangeListener {  

....  

@Override
 public void propertyChange(PropertyChangeEvent evt) {  
   if(evt.getPropertyName().equals("Domain.name")){  
     //do some work  
   }  
 }  

}

下面是个简单的测试类:


public class SimpleTest{  
 public static void main(String[] args) {  
   SimpleObserver observer = new SimpleObserver();  
   Domain domain = new Domain();  
   domain.addPropertyChangeListener(observer);  
   domain.setName("yangsq");  
   ......  
 }  
}

很显然,可以观察到SimpleObserver中propertyChange方法的执行。

标签:Java,观察者
0
投稿

猜你喜欢

  • Android深入浅出之Binder机制

    2021-07-06 01:47:21
  • SpringBoot学习篇之@Valid与@Validated的区别

    2021-08-07 21:38:41
  • Java中的this、package、import示例详解

    2021-06-10 10:37:50
  • 详解Maven私 服Nexus的安装与使用

    2023-11-24 12:34:02
  • Kotlin可见性修饰符详解

    2023-02-28 22:36:18
  • Android 显示和隐藏输入法实现代码

    2023-03-29 06:42:39
  • Java解决No enclosing instance of type PrintListFromTailToHead is accessible问题的两种方案

    2022-10-30 00:31:51
  • Android开发高级组件之自动完成文本框(AutoCompleteTextView)用法示例【附源码下载】

    2021-09-14 08:23:54
  • 关于Controller层和Service层的类报错问题及解决方案

    2023-09-28 15:12:23
  • Java基础之String类使用与字符串比较

    2023-11-09 23:46:51
  • MVC设定默认路由为指定的Area下的某个action

    2023-03-03 00:00:56
  • Java Swing实现窗体添加背景图片的2种方法详解

    2021-10-26 19:01:18
  • Spring Boot thymeleaf模板引擎的使用详解

    2022-07-27 07:42:54
  • android自定义view之模拟qq消息拖拽删除效果

    2023-01-29 11:48:34
  • java 基础之JavaBean属性命名规范问题

    2022-10-09 05:44:22
  • android JSON解析数据 android解析天气预报

    2022-01-16 03:33:53
  • Spring Boot和Vue前后端分离项目架构的全过程

    2023-09-20 17:49:13
  • java多线程入门知识及示例程序

    2021-11-30 03:17:58
  • Android应用框架之应用启动过程详解

    2023-06-05 02:20:47
  • c#在控制台输出彩色文字的方法

    2021-07-17 03:46:51
  • asp之家 软件编程 m.aspxhome.com