当前位置:  技术问答>java相关

有没有对Class:Observer,熟悉的?

    来源: 互联网  发布时间:2015-03-28

    本文导语:  熟悉的话请讲一下它的流程。谢谢!!! | 贴点东西,长了点别见怪 一种设计模式 Observer模式的功用,是希望两个(或多个)对象,我们称之为Subject和Observer,当一方的状态发生改变的时候...

熟悉的话请讲一下它的流程。谢谢!!!

|
贴点东西,长了点别见怪

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




    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 有没有和dotNet里面System.Reflection.Emit对应的class
  • java中有没有destructor的东东,好像一般的class里都没有嘛,难道不要手工做这些事情,全部交给gc处理吗?
  • 请问各位大侠有没有防止class被反编译的方法?多多益善
  • 请教:有没有把java编译好的.java和.class文件编译成各个平台下的可执行文件??.exe?着急着急
  • 请问有没有把java的class文件反编译成“字节码”的程序?
  • [AIX]有没有办法查到有没有用户执行了Kill命令
  • linux里有没有象vc那样的IDe啊,有没有类库什么的呢
  • 有没有用过 JCE 的朋友,生成x.509证书,有没有免费算法,用哪家的比较好,给出示例代码!
  • 请问jsp有没方法判断窗口有没有框架???
  • 有没有哪位知道linux下有没有什么可视聊天的工具
  • 在linux redhat6.0中,进入x_window,请问系统有没有自带的c编译器,比如gcc;如果没有,那里可以下载并安装? iis7站长之家
  • 有没有搞错,JSP精华版数据全部没有了。
  • 我想在VMware上装FreeBSD,有没有人这样做过?有什么问题没有?
  • 我重装了winme,却进不了Linux了,而我现在又没有Linux光盘,也没有Linux启动盘,还有没有办法?
  • Qt中有没有类似VB中winsock和timer的控件呀,我好像没有找到.
  • 转 请大家讨论一下,现在我们开发J2EE的Application Server还有没有机会,这里有没有这种人才? (愿意给300分)
  • 有没有用过ejb,又开始学com的,如果有,介绍一下经验?没有,则给个理由(如果你有时需要用DNA)?
  • 在linux redhat6.0中,进入x_window,请问系统有没有自带的c编译器,比如gcc;如果没有,那里可以下载并安装?
  • JAVA中没有宏,那编程和调试起来不是很麻烦吗?有没有一些折中办法?
  • SCJP有没有用
  • InstallShield 有没有linux版本的?
  • 有没有玩的转LINUX源码的高手?
  • 谁知道现在有没有Linux下的搜索引擎?
  • 谁知道现在有没有Linux下的搜索引擎??
  • 【GTK】GTK中有没有这个widget?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3