Observer模式 学习笔记1

Observer模式 学习笔记1
GOF的设计模式中是这样描述Observer模式的意图(intent)的:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

我自己的理解是:
        Observer模式定义了一种多个对象之间的一对多的相互依赖关系,当一个对象的状态发生改变时,其他与之有关系的对象“看上去”都要相应采取行动。


试着用Observer模式写了一些代码,模拟灌篮比赛,运动员每次灌完之后,评委为他们打分。
在这里Player是Subject;
ChinesePlayer和USPlayer是ConcreteSubject;
Rater是Observer
DunkRater是ConcreteObserver

Player中的endPlaying方法就是Player的行为或(引起观察者行为的)事件。
Rater中的rate方法是观察者的响应行为。           

         

  1public abstract class Player
  2{
  3    protected String name;
  4    protected int height;
  5    public String getPlayerName()
  6    {
  7        return this.name;
  8    }

  9    
 10    public int getPlayerHeight()
 11    {
 12        return this.height;
 13    }

 14    private ArrayList<Rater> raterList = new ArrayList<Rater>();
 15    
 16    public void addRater(Rater rater)
 17    {
 18        this.raterList.add(rater);
 19    }

 20    
 21    public void removeRater(Rater rater)
 22    {
 23        this.raterList.remove(rater);
 24    }

 25    
 26    protected void askForRating()
 27    {
 28        for(Rater rater : this.raterList)
 29        {
 30            rater.rate();
 31        }

 32    }

 33    
 34    /**//*
 35    这里不写成dunk()是为了以后的扩展之用,因为可能现在开发的是灌篮比赛,
 36    以后再加入其他类型的比赛,比如投篮。
 37    可以采用策略模式来完成。
 38    */

 39    public void play()    
 40    {    
 41        //some code to describe play
 42    }

 43    
 44    public void endPlaying()
 45    {
 46        askForRating();
 47    }

 48}

 49
 50public class ChinesePlayer extends Player
 51{
 52    public ChinesePlayer(String name)
 53    {
 54        this.name = name;
 55    }

 56    
 57    public void play()
 58    {
 59        System.out.println(this.name + " have a power dunk"); 
 60    }

 61}

 62
 63public class USPlayer extends Player
 64{
 65    public USPlayer(String name)
 66    {
 67        this.name = name;
 68    }

 69    
 70    public void play()
 71    {
 72        System.out.println(this.name + " have a highflyer dunk"); 
 73    }

 74}

 75
 76public abstract class Rater
 77{
 78    protected String name;
 79    public abstract void rate();
 80}

 81
 82public class DunkRater extends Rater
 83{
 84
 85    public DunkRater(String name)
 86    {
 87        this.name = name;
 88    }

 89    
 90    public void rate()
 91    {
 92        // TODO 自动生成方法存根
 93        int score = (int)(Math.random() * 8+ 2;
 94        System.out.println(this.name + "" + score);
 95    }

 96
 97}

 98
 99public class DunkGame
100{
101    public static void main(String[] args)
102    {
103        Rater rater1 = new DunkRater("Kobe");
104        Rater rater2 = new DunkRater("Jordan");
105    
106        Player player1 = new ChinesePlayer("Yao Ming");
107        Player player2 = new USPlayer("James");
108        
109        player1.addRater(rater1);
110        player1.addRater(rater2);
111    
112        player2.addRater(rater1);
113        player2.addRater(rater2);
114        
115        player1.play();
116        player1.endPlaying();
117        
118        player2.play();
119        player2.endPlaying();
120    }

121    
122}

123


某一次打印出的结果如下:
Yao Ming have a power dunk
Kobe: 4
Jordan: 4
James have a highflyer dunk
Kobe: 7
Jordan: 5

  
 几点讨论:

1)在Player(Subject)中的那个raterList是否可以把private改为protected?
   我觉得改了不好,因为不应该把“用什么数据结构、何种方式保存Rater(Observer)”暴露给用户。(客户程序员,他们可以扩展Player这个抽象类),否则就违背了封装性。

2)从面向对象的几个原则来看Observer模式
    a)把变化的部分封装起来:
       我们可以很好地扩展Player和Rater两个部分,彼此没有过多影响。因此Observer模式在方面做的还是很好的。
      ConcretePlayer与ConcreteRater这间的联系就是ConcretePlayer维护着一个注册过的现有的Rater(Observer)的列表(这个列表的实现方式对于负责扩展地程序员应该是透明的),ConcretePlayer不知道它的监听者具体是什么类型,只知道它们实现了Rater(Observer)的接口。
       

    b)面向接口编程而不是面向实现
      在客户主程序中,只出现了三个具体的类,这样的问题可以通过工厂模式解决。
      值得注意的一点,也是Head First in Design Patterns中对于这条原则的一个解释:
       一直以来我们所说的面向对象设计中很重要的一条原则--面向接口编程,再加之继承存在的种种问题,容易使人产生错觉:使用关键字interface。
      实际上这条原则的一个等价的说法是 “面向SuperType编程”。这里的SuperType的意思是接口或者超类。
      因此用abstract class并没有违反这样的原则,反而是遵守了。

3)语义上与实现上是否是相反的
   我不明白是翻译问题还是我自己没懂,总觉得GOF的描述中“自动”二字和“观察者”会给读者带来误解。
   原因如下:
        Observer模式描述的是这样的一种情况:
        当一个Subject的状态发生变化或被触发了一个事件的时候,在这个Subject上注册的对象要依据这样的变化或事件做出相应的反映,这些对象然后被称之为Observers。
        按照GOF的说法,从语义上来说应该是Observer主动响应了这个行为。
        但在实现上应该是Subject调用Observer的这个响应行为,这就是我上面所说的“看上去”主动响应,实际上是被动地被Subject调用。
        因此Observer和自动不免给人带来误解,站在Subject的角度上给这个模式取名,叫作通知者模式也许更好。
        
        
        这个例子,以后会重构,将其他模式应用上去。在网上学习的过程中,知道Observer模式和责任链模式、MVC模式会有组合,但我现在还没有学到,就先写这些吧。
        

       


      
  
 



        
       
         
 



你可能感兴趣的:(Observer模式 学习笔记1)