About Observer & Observable

从字面意义上看:Observer观察者,Observable可观察的。当然是观察者对可观察的对象进行观察。乍一看,这观察没什么难的,用普通的 if 语句就可以实现这个功能,但其实这里的Observer Pattern是有一些很好的优点的。

 

看程序前,先通过API对Observer Pattern进行最基本,最准确的认识和理解。

----------------------------------------------------------------------------------------------------------------------------------

先看java.util.Observable,不要被其名字所误导(因为名字看起来像个interface,如接口comparable就是这样类型的名字),它其实是一个类。如果想让某个类被观察,只要将这个类继承Observable就行了。

 

其主要的方法有:

void addObserver(Observer o)      ---添加观察者

boolean hasChanged()                  ---测试对象是否改变

protected void setChanged()         ---标记此Observable对象为已改变对象;此时hasChanged()返回true

void notifyObservers(Object arg)   ---如果hasChanged()方法指示对象已改变,则通知其所有观察者,并调用clearChanged()方法指示此对象不再改变。

protected void clearChanged()      ---指示对象不再改变,所以此时hasChanged()返回false

----------------------------------------------------------------------------------------------------------------------------------

再看java.util.Observer,它是一个接口。实现这个接口的类,可以对Observable对象进行观察。

 

其主要的方法有:

void update(Observable o, Object arg)   ---当调用Obserbable对象的notifyObservers时,此方法作出响应。

----------------------------------------------------------------------------------------------------------------------------------

 

讲一个实例:

 

程序结构是这样的:

 

 

 

Java代码   收藏代码
  1. import java.util.Observable;  
  2.   
  3. public class Product extends Observable  
  4. {  
  5.     private String name;  
  6.     private double price;  
  7.       
  8.     public Product()  
  9.     {  
  10.         String defaultName ="default name";  
  11.         name = defaultName;  
  12.         double defaultPrice = 100;  
  13.         price = defaultPrice;  
  14.     }  
  15.       
  16.     public void setName(String currentName)  
  17.     {  
  18.         System.out.println("Previous name is:"+name);  
  19.         name=currentName;  
  20.         setChanged();  
  21.         System.out.println("Now the method hasChanged() return:"+hasChanged());  
  22.         notifyObservers(currentName);  
  23.         System.out.println("Now the method hasChanged() return:"+hasChanged()+"\n\n");  
  24.     }  
  25.       
  26.     public void setPrice(double currentPrice)  
  27.     {  
  28.         System.out.println("Previous price is:"+price);  
  29.         price=currentPrice;  
  30.         setChanged();  
  31.         System.out.println("Now the method hasChanged() return:"+hasChanged());  
  32.         notifyObservers(currentPrice);  
  33.         System.out.println("Now the method hasChanged() return:"+hasChanged()+"\n\n");  
  34.     }  
  35. }  

 

 

Java代码   收藏代码
  1. import java.util.Observer;  
  2. import java.util.Observable;  
  3.   
  4. public class PriceObserver implements Observer  
  5. {  
  6.     public void update(Observable o,Object arg)  
  7.     {  
  8.         if(arg instanceof Double)  
  9.         System.out.println("Name changed to :"+arg);  
  10.     }  
  11. }  

 

 

Java代码   收藏代码
  1. import java.util.Observer;  
  2. import java.util.Observable;  
  3.   
  4. public class NameObserver implements Observer  
  5. {  
  6.     public void update(Observable o,Object arg)  
  7.     {  
  8.         if(arg instanceof String)  
  9.         System.out.println("Name changed to :"+arg);  
  10.     }  
  11. }  

 

 

还有最后一个是测试类:

 

 

Java代码   收藏代码
  1. public class Tester  
  2. {  
  3.     public void test()  
  4.     {  
  5.         Product pro = new Product();  
  6.         pro.addObserver(new NameObserver());  
  7.         pro.addObserver(new PriceObserver());  
  8.           
  9.         System.out.println("The class Product has "+pro.countObservers()+" Observers.\n");  
  10.           
  11.         pro.setName("NEW NAME");  
  12.         pro.setName("ANOTHER NEW NAME");  
  13.           
  14.         pro.setPrice(200);  
  15.         pro.setPrice(300);  
  16.     }  
  17. }  

 

程序的输出结果如下:

 

 

 

 

程序运行的主线流程是这样的:

1. 为Product 的对象添加观察者,pro.addObserver(new NameObserver());

 

2.由于setName方法中设置了观察点(setChanged(); )

   所以,当Product 的对象发生改变时候,pro.setName("NEW NAME");

   会触发 notifyObservers(currentName);)这个方法是以setChanged()为基础的,或者说是以hasChanged()为

   基础的,因为setChanged()改变hasChanged()的返回值!

 

   3.调用Observer接口类中的update方法,是该类作出响应(NameObserver)。

      响应是:System.out.println("Name changed to :"+currentName);

  

 

 

接下来,看看这种Pattern的特殊之处。

    以前,如果想实现一个类内部的观察监督,理论上是要用if语句(其实我觉得对于一个类来说,这样更好),但是有时候是要实现一个类改变,引发其他类跟着改变的!

    这是,如果想要观察者类发生改变,就需要在被观察对象的代码中创建观察者的实例。这样就出现了调用的情况,耦合性加大了。

    此时,如果应用Observer Pattern,便会降低耦合性,符合高内聚,低耦合的设计原则。

 

     此外,Observer Pattern 还有如下特点(由于使用太少,经验不多,所以摘除网上内容,便以后深入理解):

----------------------------------------------------------------------------------------------------------------------------------

    优点:

    是实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,类别清晰,并 
    抽象了更新接口,使得可以有各种各样不同的表示层(观察者)。 

 

   1、  Subject和Observer之间是松偶合的,分别可以各自独立改变,不互相依赖。

2、  Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。

3、  遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

 

    缺点:

1、如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会 
             花费很多时间。 
2、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致 
             系统崩溃。在使用观察考模式时要特别注意这一点。 
3、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自 
             恰的方式进行的。 
4、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没 
             有相应的机制使观察者知道所观察的对象是怎么发生变化的。

 

form:http://mynamesky.iteye.com/blog/450194



http://thinkingmt.iteye.com/blog/1036199

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值