一:身边的观察者模式

传统的报纸和杂志的订阅就是一种观察者模式:
  1. 报社的业务就是出版报纸
  2. 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸来。
  3. 当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。
  4. 只要报社还在运营,就会有人(或单位)向他们订阅报纸或取消订阅报纸。

  

二:什么是观察者模式

  • 由报社和订报人的关系可以看出:出版者+订阅者 = 观察者模式

 

  • 观察者模式:定义了对象之间的一对多依赖,当一个对象改变状态时,它所有的依赖者都会收到通知并自动更新。

 

  • 定义观察者模式

 

  • 《interface》Subject:主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。
  • ConcreteSubject:具体主题,实现了主题接口,除了注册和撤销方法之外,具体主题还实现了notifyObservers(),此方法用于在状态改变时更新所有当前观察者。
  • 《interface》Observer:观察者接口,这个接口只有update()一个方法,当主题状态改变时它被调用。
  • Observer:具体观察者,必须注册具体主题,以便接受更新。

 

当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象涉及,让主题和观察者之间松耦合

 

三:下面我拿lol游戏中的实景来写段代码,体现游戏中的观察者模式(为了更好的理解,我们先不用java内置支持):

主人公:我方中路(solo无解的流浪法师),下路(寄托希望的寒冰箭手),上路(万年蹲的德玛西亚),野区(打野的木木)。

    对方中路(高出我们战斗力5000的大神阿卡丽)。

场景:————————————————出门前——————————————————————

    寒冰:流浪,对面阿卡丽有点牛逼,她如果中路消失的话你提醒下我啊![此时,寒冰就成了观察者(observe),而流浪则是主题(subject),寒冰向他注册了(registerObserver()),希望阿卡丽gank的时候提醒下自己(notifyObservers())]

    流浪:OK![此时,流浪的观察者队列里面已经添加了寒冰]

    德玛西亚:¥%¥&%&(……¥%¥  [对流浪说了同样的话,又增加了一个观察者]。

    木木:我打野,我不关心  [那他现在就是个路人甲。。]

 

让我们先来实现主题的接口类: 

1 public interface Subject {
2 
3     public void registerObserver(Observer o);//注册观察者
4     
5     public void removeObserver(Observer o);//解除观察者
6     
7     public void notifyObservers();//通知观察者
8     
9 }

 

观察者的接口类:

1 public interface Observer {
2     
3     public void update(String alarm);//当被观察者发生变化时,调用观察者的update,把alarm发给观察者。
4     
5     public void action();//观察者的行为
6     
7 }

 

 流浪:

 1 import java.util.ArrayList;
 2 
 3 
 4 public class RogueMage implements Subject {
 5 
 6     private ArrayList<Observer> observers;
 7     private boolean isMiss = false;//阿卡丽是否消失
 8     public static String ALARM = "我了个去,阿卡丽不见了!--本条消息来自流浪法师";
 9     public static String SAFE = "她在线上呢!--本条消息来自流浪法师";
10     public int level;
11     
12     public RogueMage() {
13         observers = new ArrayList<Observer>();
14     }
15 
16     @Override
17     public void registerObserver(Observer o) {
18         // TODO Auto-generated method stub
19         if(observers.contains(o) == false){
20             observers.add(o);
21         }
22     }
23 
24     @Override
25     public void removeObserver(Observer o) {
26         // TODO Auto-generated method stub
27         if(observers.contains(o) == true){
28             observers.remove(o);
29         }
30     }
31 
32     @Override
33     public void notifyObservers() {
34         // TODO Auto-generated method stub
35         for(int i = 0;i < observers.size();i++){
36             observers.get(i).update(ALARM);
37         }
38     }
39     
40     private void isMissing(){//阿卡丽消失了
41         System.out.println(ALARM);
42         System.out.println();
43         System.out.println("-----------------------------------");
44         notifyObservers();
45     }
46     
47     public void setMissingState(boolean isMiss){//设置阿卡丽状态
48         this.isMiss = isMiss;
49         if(isMiss == true){
50             isMissing();
51         }
52     }
53     
54     public int getLevel(){//获取阿卡丽等级
55         return level;
56     }
57     
58     public void setLevel(int level){//设置阿卡丽等级
59         this.level = level;
60     }
61 }

 

 

 

寒冰:

 

 1 public class FrostArcher implements Observer{
 2 
 3     private Subject subject;
 4     
 5     public FrostArcher(Subject subject) {
 6         this.subject = subject;
 7         subject.registerObserver(this);
 8     }
 9     
10     @Override
11     public void update(String alarm) {
12         // TODO Auto-generated method stub
13         if(alarm.equals(RogueMage.ALARM)){
14             action();
15         }
16     }
17 
18     @Override
19     public void action() {
20         // TODO Auto-generated method stub
21         System.out.println("寒冰射手:好可怕,我还是缩塔好了。");
22     }
23     
24     
25 }

 

 

德玛西亚:

 

 1 public class Garen implements Observer {
 2     private Subject subject;
 3     
 4     public Garen(Subject subject) {
 5         this.subject = subject;
 6         subject.registerObserver(this);
 7     }
 8 
 9     @Override
10     public void update(String alarm) {
11         // TODO Auto-generated method stub
12         if(alarm.equals(RogueMage.ALARM)){
13             action();
14         }
15     }
16 
17     @Override
18     public void action() {
19         // TODO Auto-generated method stub
20         System.out.println("德玛西亚:我在草丛,她看不见我看不见我~");
21     }
22 
23 }

 

 

OK!战斗前准备就绪,全军偷鸡!

 

 1 public class Begin {
 2     
 3     public static void  main(String[] agrs){
 4         
 5         //战斗开始,人物诞生
 6         //寒冰和德玛西亚跟流浪法师打招呼,要求阿卡丽消失通知自己
 7         RogueMage rogueMage = new RogueMage();
 8         FrostArcher frostArcher = new FrostArcher(rogueMage);
 9         Garen garen = new Garen(rogueMage);
10         
11         System.out.println("----------战斗开始10分钟,流浪法师发现阿卡丽消失-------------");
12         rogueMage.setMissingState(true);//流浪法师发现阿卡丽消失。
13         
14     }
15 }

 

 

 

 

结果:

 

 得益于我们简单的观察者模式,阿卡丽第一次gank没有成功,寒冰和德玛西亚他们都躲得远远的,是不是很开心~。

 

有时候并不是所有的队友会要求别人积极的告诉你关注的消息(推送消息),而且所有人关注的东西都不一样,比如木木,他不怕阿卡丽gank。相反,由于自信,他希望阿卡丽再次gank的时候,自己能从流浪那获取阿卡丽的等级帮助队友反杀,所以我们只好来让木木获得消息(拉取消息)。

 

木木:

 

 1 public class Sadmummy implements Observer {
 2 
 3     private Subject subject;
 4     private RogueMage rogue;
 5     
 6     
 7     public Sadmummy(Subject subject) {
 8         this.subject = subject;
 9         if(subject instanceof RogueMage){
10             rogue = (RogueMage)subject;
11         }
12         subject.registerObserver(this);
13     }
14 
15 
16     
17     @Override
18     public void update(String alarm) {
19         // TODO Auto-generated method stub
20         if(alarm.equals(RogueMage.ALARM)){
21             action();
22         }
23     }
24 
25     @Override
26     public void action() {
27         // TODO Auto-generated method stub
28         int level = rogue.getLevel();
29         System.out.println("木木:阿卡丽才"+level+"级,看我去啪啪啪了她");
30     }
31 
32 }

 

 

继续玩:

 1 public class Begin {
 2     
 3     public static void  main(String[] agrs){
 4         
 5         //战斗开始,人物诞生
 6         //寒冰和德玛西亚跟流浪法师打招呼,要求阿卡丽消失通知自己
 7         //木木和流浪法师打招呼,要求阿卡丽消失的时候也通知自己
 8         RogueMage rogueMage = new RogueMage();
 9         FrostArcher frostArcher = new FrostArcher(rogueMage);
10         Garen garen = new Garen(rogueMage);
11         
12         System.out.println("----------战斗开始10分钟,流浪法师发现阿卡丽消失-------------");
13         rogueMage.setMissingState(true);//流浪法师发现阿卡丽消失。
14         
15         
16         
17         Sadmummy mumumy = new Sadmummy(rogueMage);
18         System.out.println();
19         System.out.println();
20         System.out.println("-----------战斗开始20分钟,流浪法师发现阿卡丽再次消失----------");
21         rogueMage.setLevel(10);//因为木木要知道阿卡丽等级
22         rogueMage.setMissingState(true);//流浪法师发现阿卡丽消失
23         
24         
25         
26     }
27 }

 

 

结果:

 

 

不出意料,由于用了我们的观察者模式,这次阿卡丽不但没有杀人成功还丢了firstBlood,高手怎么能忍受这耻辱,果断退出了游戏,小伙伴们取得了胜利,喜大普奔啊~

 

四:代码中的观察者

  • 比如button中的listener,当button注册了监听的时候,当界面观察到button被点击则会通知button调用onclick()的方法;
  • android中的 BroadcastReceiver注册了监听intent,当系统收到intent符合条件时会通知BroadcastReceiver调用onreceive();
  • MVC--模型(model)-视图(view)-控制器(controller),典型的观察者模式。

 

 

OO原则:

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力

 

 

 

 

 

 

 

posted on 2013-09-09 15:32  dwj111  阅读(426)  评论(0编辑  收藏  举报