zoukankan      html  css  js  c++  java
  • 设计模式Observer(观察者模式)

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

    Observer模式应该可以说是应用最多、影响最广的模式之一,因为Observer的一个实例Model/View/Control(MVC)结构在系统开发架构设计中有着很重要的地位和意义,MVC实现了业务逻辑和表示层的解耦。个人也认为Observer模式是软件开发过程中必须要掌握和使用的模式之一。在MFC中,Doc/View(文档视图结构)提供了实现MVC的框架结构(有一个从设计模式(Observer模式)的角度分析分析Doc/View的文章正在进一步的撰写当中,遗憾的是时间:))。在Java阵容中,Struts则提供和MFC中Doc/View结构类似的实现MVC的框架。另外Java语言本身就提供了Observer模式的实现接口,这将在讨论中给出。
    当然,MVC只是Observer模式的一个实例。Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一个问题。


    模式结构图:



    实现:

    Observer: JDK中提供的

    /*
     * %W% %E%
     *
     * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    package java.util;
    
    /**
     * A class can implement the <code>Observer</code> interface when it
     * wants to be informed of changes in observable objects.
     *
     * @author  Chris Warth
     * @version %I%, %G%
     * @see     java.util.Observable
     * @since   JDK1.0
     */
    public interface Observer {
        /**
         * This method is called whenever the observed object is changed. An
         * application calls an <tt>Observable</tt> object's
         * <code>notifyObservers</code> method to have all the object's
         * observers notified of the change.
         *
         * @param   o     the observable object.
         * @param   arg   an argument passed to the <code>notifyObservers</code>
         *                 method.
         */
        void update(Observable o, Object arg);
    }
    

    FatherObserver:

    package com.designpatten.observer;
    
    import java.util.Observable;
    import java.util.Observer;
    
    public class FatherObserver implements Observer {
    
    	@Override
    	public void update(Observable o, Object arg) {
    		ChildObservable to = (ChildObservable)o ;
    		to.sick() ;
    		System.out.println("FatherObserver.update()=====" + arg);
    	}
    
    }
    

    MotherObserver:

    package com.designpatten.observer;
    
    import java.util.Observable;
    import java.util.Observer;
    
    public class MotherObserver implements Observer {
    
    	@Override
    	public void update(Observable o, Object arg) {
    		ChildObservable to = (ChildObservable)o ;
    		to.sick() ;
    		System.out.println("MotherObserver.update()=====" + arg);
    	}
    
    }
    

    Observable:   JDK中提供的

    /*
     * %W% %E%
     *
     * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    
    package java.util;
    
    /**
     * This class represents an observable object, or "data"
     * in the model-view paradigm. It can be subclassed to represent an 
     * object that the application wants to have observed. 
     * <p>
     * An observable object can have one or more observers. An observer 
     * may be any object that implements interface <tt>Observer</tt>. After an 
     * observable instance changes, an application calling the 
     * <code>Observable</code>'s <code>notifyObservers</code> method  
     * causes all of its observers to be notified of the change by a call 
     * to their <code>update</code> method. 
     * <p>
     * The order in which notifications will be delivered is unspecified.  
     * The default implementation provided in the Observable class will
     * notify Observers in the order in which they registered interest, but 
     * subclasses may change this order, use no guaranteed order, deliver 
     * notifications on separate threads, or may guarantee that their
     * subclass follows this order, as they choose.
     * <p>
     * Note that this notification mechanism is has nothing to do with threads 
     * and is completely separate from the <tt>wait</tt> and <tt>notify</tt> 
     * mechanism of class <tt>Object</tt>.
     * <p>
     * When an observable object is newly created, its set of observers is 
     * empty. Two observers are considered the same if and only if the 
     * <tt>equals</tt> method returns true for them.
     *
     * @author  Chris Warth
     * @version %I%, %G%
     * @see     java.util.Observable#notifyObservers()
     * @see     java.util.Observable#notifyObservers(java.lang.Object)
     * @see     java.util.Observer
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     * @since   JDK1.0
     */
    public class Observable {
        private boolean changed = false;
        private Vector obs;
       
        /** Construct an Observable with zero Observers. */
    
        public Observable() {
    	obs = new Vector();
        }
    
        /**
         * Adds an observer to the set of observers for this object, provided 
         * that it is not the same as some observer already in the set. 
         * The order in which notifications will be delivered to multiple 
         * observers is not specified. See the class comment.
         *
         * @param   o   an observer to be added.
         * @throws NullPointerException   if the parameter o is null.
         */
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
    	if (!obs.contains(o)) {
    	    obs.addElement(o);
    	}
        }
    
        /**
         * Deletes an observer from the set of observers of this object. 
         * Passing <CODE>null</CODE> to this method will have no effect.
         * @param   o   the observer to be deleted.
         */
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
        }
    
        /**
         * If this object has changed, as indicated by the 
         * <code>hasChanged</code> method, then notify all of its observers 
         * and then call the <code>clearChanged</code> method to 
         * indicate that this object has no longer changed. 
         * <p>
         * Each observer has its <code>update</code> method called with two
         * arguments: this observable object and <code>null</code>. In other 
         * words, this method is equivalent to:
         * <blockquote><tt>
         * notifyObservers(null)</tt></blockquote>
         *
         * @see     java.util.Observable#clearChanged()
         * @see     java.util.Observable#hasChanged()
         * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
         */
        public void notifyObservers() {
    	notifyObservers(null);
        }
    
        /**
         * If this object has changed, as indicated by the 
         * <code>hasChanged</code> method, then notify all of its observers 
         * and then call the <code>clearChanged</code> method to indicate 
         * that this object has no longer changed. 
         * <p>
         * Each observer has its <code>update</code> method called with two
         * arguments: this observable object and the <code>arg</code> argument.
         *
         * @param   arg   any object.
         * @see     java.util.Observable#clearChanged()
         * @see     java.util.Observable#hasChanged()
         * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
         */
        public void notifyObservers(Object arg) {
    	/*
             * a temporary array buffer, used as a snapshot of the state of
             * current Observers.
             */
            Object[] arrLocal;
    
    	synchronized (this) {
    	    /* We don't want the Observer doing callbacks into
    	     * arbitrary code while holding its own Monitor.
    	     * The code where we extract each Observable from 
    	     * the Vector and store the state of the Observer
    	     * needs synchronization, but notifying observers
    	     * does not (should not).  The worst result of any 
    	     * potential race-condition here is that:
    	     * 1) a newly-added Observer will miss a
    	     *   notification in progress
    	     * 2) a recently unregistered Observer will be
    	     *   wrongly notified when it doesn't care
    	     */
    	    if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
    
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
    
        /**
         * Clears the observer list so that this object no longer has any observers.
         */
        public synchronized void deleteObservers() {
    	obs.removeAllElements();
        }
    
        /**
         * Marks this <tt>Observable</tt> object as having been changed; the 
         * <tt>hasChanged</tt> method will now return <tt>true</tt>.
         */
        protected synchronized void setChanged() {
    	changed = true;
        }
    
        /**
         * Indicates that this object has no longer changed, or that it has 
         * already notified all of its observers of its most recent change, 
         * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>. 
         * This method is called automatically by the 
         * <code>notifyObservers</code> methods. 
         *
         * @see     java.util.Observable#notifyObservers()
         * @see     java.util.Observable#notifyObservers(java.lang.Object)
         */
        protected synchronized void clearChanged() {
    	changed = false;
        }
    
        /**
         * Tests if this object has changed. 
         *
         * @return  <code>true</code> if and only if the <code>setChanged</code> 
         *          method has been called more recently than the 
         *          <code>clearChanged</code> method on this object; 
         *          <code>false</code> otherwise.
         * @see     java.util.Observable#clearChanged()
         * @see     java.util.Observable#setChanged()
         */
        public synchronized boolean hasChanged() {
    	return changed;
        }
    
        /**
         * Returns the number of observers of this <tt>Observable</tt> object.
         *
         * @return  the number of observers of this object.
         */
        public synchronized int countObservers() {
    	return obs.size();
        }
    }
    


    ChildObservable:

    package com.designpatten.observer;
    
    import java.util.Observable;
    
    public class ChildObservable extends Observable {
    
    	public void notifyObservers(String arg){
    		super.notifyObservers(arg) ;
    	}
    	
    	public void sick(){
    		System.out.println(this.getClass().getName() + "------> sick()");
    	}
    	
    	public void changeT(){
    		super.setChanged() ;
    	}
    	
    }
    


    ObserverMain:

    package com.designpatten.observer;
    
    public class ObserverMain {
    
    	public static void main(String[] args) {
    		ChildObservable observable = new ChildObservable() ;
    		
    		FatherObserver father = new FatherObserver() ;
    		MotherObserver mother = new MotherObserver() ;
    		
    		observable.addObserver(father) ;
    		observable.addObserver(mother) ;
    		
    		observable.changeT() ;
    		if(observable.hasChanged()){
    			observable.notifyObservers("sick...") ;
    		}
    		
    	}
    	
    }
    



    讨论:

    Observer是影响极为深远的模式之一,也是在大型系统开发过程中要用到的模式之一。除了MFC、Struts提供了MVC的实现框架,在Java语言中还提供了专门的接口实现Observer模式:通过专门的类Observable及Observer接口来实现MVC编程模式,其UML图可以表示为:


    这里的Observer就是观察者,Observable则充当目标Subject的角色。
    Observer模式也称为发布-订阅(publish-subscribe),目标就是通知的发布者,观察者则是通知的订阅者(接受通知)。



    参考:C++设计模式 一书

  • 相关阅读:
    动态规划
    Python第二天学习
    Python第一天学习---基础语法
    java易错知识点
    C语言---指针复习
    排序汇总
    课程设计---创建族谱管理系统
    Vue第五篇 Vue的生命周期
    Vue第四篇 Vue路由系统
    Vue第三篇 Vue组件
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207273.html
Copyright © 2011-2022 走看看