24天学会设计模式------观察者模式

来源:互联网 发布:怎么禁用135端口 编辑:程序博客网 时间:2024/05/17 02:34

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

一、观察者模式

1、观察者模式 Observer

  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。

  这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。

2、观察者模式使用情况

(1) 当一个抽象模型有两个方面其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

(2) 当对一个对象的改变需要同时改变其它对象而不知道具体有多少对象有待改变。

(3) 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之你不希望这些对象是紧密耦合的。

3、观察者模式的组成

  抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

  抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。

  具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。

  具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。

二、使用范例

  在这里模拟了美团网的功能,你当去美团网上注册一个账号时,每当有新的团购时,就会发邮件到你邮箱。在这里,我改了下,每当有新的食物时,就发送给用户

[cpp] view plain copy
  1. /** 
  2.  
  3. * 文件名:ObserverMethod.java 
  4.  
  5. * 描述:观察者模式讲解 
  6.  
  7. * 创建人:林炳文 
  8.  
  9. * 日 期:2015.1.27 
  10.  
  11. **/  
  12.   
  13.   
  14. package linbingwen;  
  15.   
  16. import java.util.ArrayList;  
  17.   
  18.   
  19. /*抽象目标类*/  
  20. interface Subject{  
  21.         /*注册观察都者*/  
  22.         public void RegisterObserver(Observer obj);  
  23.         /*删除观察者*/  
  24.         public void RemoveObserver(Observer obj);  
  25.         /*通知所有观察都*/  
  26.         public void NotifyAllObservers(String food);  
  27.       
  28. }  
  29. /*抽象观察者类*/  
  30. interface Observer {  
  31.     public void update(String food);  
  32. }  
  33.   
  34. /*具体目标类*/  
  35. class RealSubject implements Subject{  
  36.       
  37.     private ArrayList<Observer> UserList=new ArrayList<Observer>();//用来存放观察者  
  38.     private ArrayList<String> Food=new ArrayList<String>();//用来存放有什么食物  
  39.   
  40.     @Override  
  41.     public void RegisterObserver(Observer obj) {  
  42.         UserList.add(obj);    
  43.     }  
  44.   
  45.     @Override  
  46.     public void RemoveObserver(Observer obj) {  
  47.         UserList.remove(obj);  
  48.     }  
  49.       
  50.     @Override  
  51.     public void NotifyAllObservers(String food) {  
  52.       
  53.         for(Observer obj:UserList){  
  54.             obj.update(food);  
  55.         }  
  56.     }     
  57. }  
  58.   
  59. class RealObserver implements Observer{  
  60.   
  61.      private String name;//用来保存人名  
  62.     // 根据人名来构造观察者  
  63.      public RealObserver(String name){  
  64.             this.name = name;  
  65.      }  
  66.     @Override  
  67.     public void update(String food) {  
  68.         System.out.println("通知"+name+"美团网今天有"+food+"可以吃");  
  69.     }  
  70.       
  71. }  
  72.   
  73.   
  74. public class ObserverMethod {  
  75.     public static void main(String[] args) {  
  76.       
  77.     Subject MeiTuWang=new RealSubject();//这里是美团网  
  78.     //生成三个观察者  
  79.     Observer obj1=new RealObserver("小红");  
  80.     Observer obj2=new RealObserver("德德");  
  81.     Observer obj3=new RealObserver("阿炳");  
  82.       
  83.     //注册三个观察者  
  84.     MeiTuWang.RegisterObserver(obj1);  
  85.     MeiTuWang.RegisterObserver(obj2);  
  86.     MeiTuWang.RegisterObserver(obj3);  
  87.       
  88.     //通知三个观察者,有新的食物可以吃  
  89.     MeiTuWang.NotifyAllObservers("苹果");  
  90.     MeiTuWang.NotifyAllObservers("猪肉");  
  91.     MeiTuWang.NotifyAllObservers("大米饭");  
  92.     }  
  93.   
  94. }  



输出结果:

通知小红美团网今天有苹果可以吃
通知德德美团网今天有苹果可以吃
通知阿炳美团网今天有苹果可以吃


通知小红美团网今天有猪肉可以吃
通知德德美团网今天有猪肉可以吃
通知阿炳美团网今天有猪肉可以吃


通知小红美团网今天有大米饭可以吃
通知德德美团网今天有大米饭可以吃
通知阿炳美团网今天有大米饭可以吃


三、观察者模式其它一些优缺点

下面是观察者模式其它一些优缺点:
    (1 ) 目标和观察者间的抽象耦合一个目标所知道的仅仅是它有一系列观察者, 每个都符合抽象的O b s e r v e r类的简单接口。目标不知道任何一个观察者属于哪一个具体的类。这样目标和观察者之间的耦合是抽象的和最小的。因为目标和观察者不是紧密耦合的, 它们可以属于一个系统中的不同抽象层次。一个处于较低层次的目标对象可与一个处于较高层次的观察者通信并通知它, 这样就保持了系统层次的完整。如果目标和观察者混在一块, 那么得到的对象要么横贯两个层次(违反了层次性), 要么必须放在这两层的某一层中(这可能会损害层次抽象)。
    (2) 支持广播通信不像通常的请求, 目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该目标对象登记的有关对象。目标对象并不关心到底有多少对象对自己感兴趣;它唯一的责任就是通知它的各观察者。这给了你在任何时刻增加和删除观察者的自由。处理还是忽略一个通知取决于观察者。
     (3) 意外的更新因为一个观察者并不知道其它观察者的存在, 它可能对改变目标的最终代价一无所知。在目标上一个看似无害的的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外, 如果依赖准则的定义或维护不当,常常会引起错误的更新, 这种错误通常很难捕捉。简单的更新协议不提供具体细节说明目标中什么被改变了, 这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。


林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

原创粉丝点击