设计模式-观察者模式(Observer Model)

文 / vincentzh

原文连接:http://www.cnblogs.com/vincentzh/p/6031844.html 

  LZ刚刚开始心热的开启了博客之路,想着记点流水账,可帝都的天都冷成狗了一样,还特么不供暖,冻的打字都感觉不到键盘在哪里。。。

目录

  1. 1、概述
  2. 2、原理
  3. 3、结构组成
  4. 4、实现
    1. 4.1 静态代理
    2. 4.2 动态代理
  5. 5、总结

1、概述

  观察者模式通俗讲就是一堆观察者对象同时观察一个对象的状态。好比一妹子后面跟了一群追求者,妹子一看,这仨还错,有才华、有相貌、有money,先允许你们三来竞争吧。姑娘口渴了,仨小伙急了,纷纷去给姑娘去买水,又是矿泉水又是饮料的。

2、原理

  观察者模式的原理比较简单,类似于监听,定义了一种一对多的关系,让多个观察者同时监听一个主题对象,当主题角色状态发生变化时,会通知所有观察者对象,使它们去自行更新。

3、结构组成

  观察者模式原理简单,但结构上还是稍微有点绕。其包含了4个角色:

抽象主题角色(Subject):抽象主题角色只提供一个接口,它将所有的观察者引用保存再一个容器里,同时提供增加观察者、删除观察者、通知所有观察者的方法;

具体主题角色(ConcreteSubject):具体主题角色提供一个容器保存所有观察者的引用,当其状态发生改变时,会通知在其容器内登记过的所有观察者;

抽象观察者角色(Observer):抽象观察者角色为具体观察者角色定义了一个接口,它提供了具体观察者角色更新自己的方法;

具体观察者角色(ConcreteObserver):具体观察者角色实现了抽象观察者角色定义的更新方法,以更新自己状态和主题角色状态一致,或着说相应主题角色状态的改变。

4、实现

  观察者模式的实现在4.1这里举了个例子,有点牵强,但能说明问题;4.2是利用JDK提供的接口和类去实现的观察者模式。

4.1 场景案例

  年关将至,镇长下乡去视察,看看下属各个村儿里今年的收入情况怎么样,群众有没有赚到钱呀,庄稼收成好不好呀,bulabula...。各村儿一听镇长要下乡,好家伙,赶紧趁这个机会好好表现表现,说不定明年镇长能多给村儿里几个低保名额。A村提前给镇长就做好了热腾腾的裤带面,B村知道领导都好面子,老早就搞起了锣鼓队给领导办欢迎仪式。

抽象观察者类:

1 package com.cnblogs.vincentzh.observer;
2 // 抽象观察者角色(村儿接口)
3 public interface Villages
4 {
5     public void action(String str);
6 }

 

抽象主题类:

1 package com.cnblogs.vincentzh.observer;
2 // 抽象主题角色(领导接口)
3 public interface LeaderShip 
4 {     
5      public boolean add(Villages village);
6      public boolean delete(Villages village);
7      public void notify(String str);
8 }

 

具体主题类:

 1 package com.cnblogs.vincentzh.observer;
 2 
 3 import java.util.HashSet;
 4 // 具体主题角色(镇长)
 5 public class Mayor implements LeaderShip
 6 {    
 7     // 观察者容器
 8     public HashSet<Villages> villages = new HashSet<Villages>();
 9     
10     @Override
11     public boolean add(Villages village)
12     {
13         return villages.add(village);
14     }
15 
16     @Override
17     public boolean delete(Villages village)
18     {
19         return villages.remove(village);
20     }
21     
22     @Override
23     public void notify(String str)
24     {
25         for(Villages village : villages)
26         {
27             village.action(str);
28         }
29     }
30 }

 

具体观察者类:

 1 package com.cnblogs.vincentzh.observer;
 2 // 具体观察者角色(村儿)
 3 public class Village implements Villages
 4 {
 5     private String string;
 6     
 7     public Village(String string)
 8     {
 9         this.string = string;
10     }
11     
12     @Override
13     public void action(String str)
14     {
15         System.out.println(str);
16         System.out.println(string + " for LeaderShip");
17     }
18 }

 

环境测试类:

 1 package com.cnblogs.vincentzh.observer;
 2 // 环境测试类
 3 public class Test
 4 {
 5     /**
 6      * @param args
 7      */
 8     public static void main(String[] args)
 9     {
10         LeaderShip mayor = new Mayor();
11         
12         Village village1 = new Village("village1: We cooking"); // A村做饭
13         Village village2 = new Village("village2: We welcome"); // B村欢迎
14         
15         mayor.add(village1);
16         mayor.add(village2);
17         mayor.notify("Mayor is comming!");
18         
19         System.out.println("------------------------------");
20         mayor.delete(village1);
21         mayor.notify("Mayor is comming!");
22     }
23 }

结果:

4.2 JDK实现

  JDK内部提供了用于实现观察者模式的Observable 类和 Observer 接口,它们分别充当了抽象主题角色和抽象观察者角色,要实现观察者模式,只需要定义具体主题类并继承 Observable 类重写相应的方法,同时定义具体观察者对象实现 Observer 接口并实现其中的更新方法即可。

具体主题类:

 1 package com.cnblogs.vincentzh.observermodel;
 2 
 3 import java.util.HashSet;
 4 import java.util.Observable;
 5 import java.util.Observer;
 6 // 具体主题角色(及被观察者)
 7 public class Watched extends Observable
 8 {
 9     // 观察者容器
10     private HashSet<Observer> sets = new HashSet<Observer>();    
11     
12     @Override
13     public synchronized void addObserver(Observer o)
14     {
15         sets.add(o);
16     }
17     
18     @Override
19     public synchronized void deleteObserver(Observer o)
20     {
21         sets.remove(o);
22     }
23     
24     @Override
25     public void notifyObservers()
26     {
27         for(Observer observer : sets)
28         {
29             observer.update(this, this);
30         }
31     }    
32 }

 

具体观察者类:

 1 package com.cnblogs.vincentzh.observermodel;
 2 
 3 import java.util.Observable;
 4 import java.util.Observer;
 5 // 观察者角色(即观察者)
 6 public class Watcher implements Observer
 7 {
 8     private String str;
 9     
10     public Watcher(String str)
11     {
12         this.str = str;
13     }
14         
15     @Override
16     public void update(Observable o, Object arg)
17     {
18         System.out.println((String)str);
19     }
20 }

 

环境测试类:

 1 package com.cnblogs.vincentzh.observermodel;
 2 // 环境测试类
 3 public class Test
 4 {
 5     public static void main(String[] args)
 6     {
 7         Watcher watcher1 = new Watcher("watched1");
 8         Watcher watcher2 = new Watcher("watched2");
 9         
10         Watched watched = new Watched();
11         
12         watched.addObserver(watcher1);
13         watched.addObserver(watcher2);
14         watched.notifyObservers();
15         
16         System.out.println("---------------------------");
17         
18         watched.deleteObserver(watcher1);
19         watched.notifyObservers();
20     }
21 }

 

结果:

5、总结

   观察者模式对主题对象和观察者对象进行了解耦,使双方都依赖于抽象,而并不是依赖于对方的具体对象,使得双方各自的变化都不会影响到对方的具体对象。但双方并没有完全的独立,抽象主题通知时仍然依赖于抽象观察者。当其他多个对象需要根据一个对象的状态发生相应的改变或操作时(或类似发布/订阅模式),可使用观察者模式来解决。

 

posted @ 2016-11-04 22:05  vincentzh  阅读(724)  评论(0编辑  收藏  举报