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++设计模式 一书

  • 相关阅读:
    .net core 3.1 使用Redis缓存
    JavaSE 高级 第11节 缓冲输入输出字节流
    JavaSE 高级 第10节 字节数组输出流ByteArrayOutputStream
    JavaSE 高级 第09节 字节数组输入流ByteArrayInputStream
    JavaSE 高级 第08节 文件输出流FileOutputStream
    JavaSE 高级 第07节 文件输入流FileInputStream
    JavaSE 高级 第06节 初识I、O流
    JavaSE 高级 第05节 日期类与格式化
    JavaSE 高级 第04节 StringBuffer类
    JavaSE 高级 第03节 Math类与猜数字游戏
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207273.html
Copyright © 2011-2022 走看看