zoukankan      html  css  js  c++  java
  • 每天一个设计模式(2):观察者模式

    2.观察者模式

      观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

    一.要点

    •  观察者模式定义了对象之间的一对多的关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
    •  主题(被观察者)通过一个共同的接口来更新观察者。
    •  有多个观察者时,不可以依赖特定的通知次序。
    •  观察者模式提供了一种对象设计,让主题和观察者之间松耦合。改变主题或者观察者其中一方,并不会影响另一方。
    •  使用此模式时,可以从被观察者处推(push)或拉(pull)数据。
    •    Java有多种观察者模式的实现,包括了通用的java.util.Observable。
    •    如果有必要的话,可以实现自己的Observable。
    •    在JavaBeans和Swing中,也都实现了观察者模式。

    二.设计原则

     1.当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

      当有新的具体类需要作为观察者时,要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。

     2.找出程序中会变化的方面,然后将其和固定不变的方面相分离。

      在观察者模式中,会改变的是主体的状态,以及观察者的数目和类型。用这个模式,你可以改变依赖于主题状态的的对象,却不必改变主题。这就叫提前规则!

     3.针对接口编程,不针对实现编程。

      主题和观察者都是用接口,观察者利用主题的接口向主题注册,而主题利用观察者的而接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点。

     4.多用组合,少用继承。

      观察者模式利用“组合”将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合方式而产生的。

    三.UML关系图

      图中,MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。

    四.Java内置的观察者模式

      主题(被观察者):扩展自java.util.Observable。(因为是类,所以存在一定的局限性)。

      观察者:实现java.util.Observer接口。

    通过调用Observable对象的addObserver()和deleteObserver()方法添加或者删除观察者。

      被观察者送出通知时,需要两个步骤:

      1.调用setChanged()方法,标记状态已经改变的事实;

      2.调用两种notifyObservers()方法中的一个:

      notifyObservers()或notifyObservers(Object arg):当通知时,后者的版本可以传送任何的数据对象给每一个观察者。

      观察者接收通知:

      update(Observable o, Object arg)

      主题本身是第一个参数,第二个参数为notifyObservers(Object arg)的数据对象,如果没有则为空。

      Java内置的Observer模式支持push和pull两种数据传递方式:

      push:由被观察者把数据推给观察者。

      pull:观察者从被观察者中拉数据。

    五.实现代码

    一个Observer接口:

    public interface Observer {  
        public void update();  
    }  
    

    一个实现类:

    public class Observer1 implements Observer {  
      
        @Override  
        public void update() {  
            System.out.println("observer1 has received!");  
        }  
    }  
    

    Subject接口:

    public interface Subject {  
          
        /*增加观察者*/  
        public void add(Observer observer);  
          
        /*删除观察者*/  
        public void del(Observer observer);  
          
        /*通知所有的观察者*/  
        public void notifyObservers();  
          
        /*自身的操作*/  
        public void operation();  
    }  
    

    Subject实现类:

    public abstract class AbstractSubject implements Subject {  
      
        private Vector<Observer> vector = new Vector<Observer>();  
        @Override  
        public void add(Observer observer) {  
            vector.add(observer);  
        }  
      
        @Override  
        public void del(Observer observer) {  
            vector.remove(observer);  
        }  
      
        @Override  
        public void notifyObservers() {  
            Enumeration<Observer> enumo = vector.elements();  
            while(enumo.hasMoreElements()){  
                enumo.nextElement().update();  
            }  
        }  
    }  
    
    
    public class MySubject extends AbstractSubject {  
      
        @Override  
        public void operation() {  
            System.out.println("update self!");  
            notifyObservers();  
        }  
      
    }  
    

    测试类:

    public class ObserverTest {  
      
        public static void main(String[] args) {  
            Subject sub = new MySubject();  
            sub.add(new Observer1());   
              
            sub.operation();  
        }  
      
    }  
    

    输出:

    update self!
    observer1 has received!

    参考:

    《Head Frist 设计模式》

    http://blog.csdn.net/zhangerqing/article/details/8243942

    http://www.cnblogs.com/mengdd/archive/2013/01/03/2843298.html

  • 相关阅读:
    责任链简单解析
    mysql实践一:SQL基础
    Aix6.1下su命令不能切换环境变量的问题
    maven 打包错误 Cannot access central in offline mode
    登陆并访问k8s的apiserver
    kubernetes 实践五:Service详解
    kubernetes1.16 配置 metrics-server
    kubernetes 实践四:Pod详解
    kubernetes 实践三:使用kubeadm安装k8s1.16.0
    kubernetes 实践二:kubectl命令使用
  • 原文地址:https://www.cnblogs.com/Eason-S/p/5660209.html
Copyright © 2011-2022 走看看