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

    一:基本概念

    1.什么是观察者模式

    • Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
    • Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。

    2.观察者模式的UML结构

    3.观察者模式的角色和职责

    • Subject(被观察者)     被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
    • ConcreteSubject     被观察者的具体实现。包含一些基本的属性状态及其他操作。
    • Observer(观察者)     接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
    • ConcreteObserver     观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

    4.观察者模式的典型应用

    • Observer模式的典型应用
      • 侦听事件驱动程序设计中的外部事件
      • 侦听/监视某个对象的状态变化
      • 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者

    二:具体例子

    1.功能需求描述:发布一条新闻的时候,观察者可以观察到。

    2.具体实现:

    2.1.效果:

      

    2.2.项目结构

    • Article.java-文章bean
    • MyObservable.java-被观察者要实现的基类
    • MyObserver.java-观察者要实现的接口
    • NewsMainClass.java-启动方法
    • ObserverNews.java-实现了观察者接口的类
    • ObserverNews1.java-实现了观察者接口的类
    • PublisherArticle.java-实现了被观察者的类

      

    2.3.运行流程

    2.3.1.NewsMainClass.java类主要将,观察者对象注入到被观察者对象中。

    package com.witwicky.myobserver;
    
    public class NewsMainClass {
    	public static void main(String[] args) {
    		Article article = new Article("title1", "content1");
    
    		PublisherArticle pa = new PublisherArticle();
    
    		ObserverNews obn = new ObserverNews();
    		ObserverNews1 obn1 = new ObserverNews1();
    
    		pa.addOberserver(obn);
    		pa.addOberserver(obn1);
    
    		pa.removeOberserver(obn1);
    		// pa.removeAll(); //可以使用
    
    		pa.publisherArt(article);
    	}
    }
    

    2.3.2.Article.java-文章bean

    package com.witwicky.myobserver;
    
    public class Article {
    	private String title;
    	private String content;
    
    	public Article(String title, String content) {
    		this.title = title;
    		this.content = content;
    	}
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    	public String getContent() {
    		return content;
    	}
    
    	public void setContent(String content) {
    		this.content = content;
    	}
    
    	@Override
    	public String toString() {
    		return "Article [title=" + title + ", content=" + content + "]";
    	}
    
    }
    

    2.3.3.MyObservable.java-被观察者要实现的基类

    自己实现:

    package com.witwicky.myobserver;
    
    import java.util.Vector;
    
    public class MyObservable {
    	private Vector<MyObserver> observerList = new Vector<>();
    
    	public void notifyObservers() {
    		notifyObservers(null);
    	}
    
    	public void notifyObservers(Object object) {
    		for (MyObserver myObserver : observerList) {
    			myObserver.update(myObserver, object);
    		}
    	}
    
    	public void addOberserver(MyObserver observer) {
    		if(!observerList.contains(observer)) {
    			observerList.addElement(observer);
    		}
    	}
    
    	public void removeOberserver(MyObserver observer) {
    		observerList.remove(observer);
    	}
    
    	public void removeAll() {
    		observerList.removeAllElements();
    	}
    
    	public Integer obsCount() {
    		return observerList.size();
    	}
    }
    

     JDK中官方实现:

    /*
     * Copyright (c) 1994, 2012, 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 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
     * @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<Observer> 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();
        }
    }
    

    2.3.4.MyObserver.java-观察者要实现的接口

    自己实现:

    package com.witwicky.myobserver;
    
    public interface MyObserver {
    	public void update(MyObserver myobserver, Object object);
    }
    

    JDK官方实现:

    /*
     * Copyright (c) 1994, 1998, 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
     * @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);
    }
    

    2.3.5.ObserverNews.java-实现了观察者接口的类

    package com.witwicky.myobserver;
    
    public class ObserverNews implements MyObserver {
    
    	@Override
    	public void update(MyObserver myobserver, Object object) {
    		System.out.println("观察者:观察到又发布了一条新闻,内容如下:"+object.toString());		
    	}
    	
    }
    

    2.3.6.ObserverNews1.java-实现了观察者接口的类

    package com.witwicky.myobserver;
    
    public class ObserverNews1 implements MyObserver {
    
    	@Override
    	public void update(MyObserver myobserver, Object object) {
    		System.out.println("观察者1:观察到又发布了一条新闻,内容如下:"+object.toString());		
    	}
    	
    }
    

    2.3.7.PublisherArticle.java-实现了被观察者的类

    package com.witwicky.myobserver;
    
    public class PublisherArticle extends MyObservable {
    	public void publisherArt(Article article) {
    		System.out.println("发布者:发布了新文章:" + article.toString());
    		this.notifyObservers(article);
    		
    		System.out.println(this.obsCount());
    	}
    }
    

    注:最关键的两个类是 MyObserver与MyObservalbe,自己实现代码更灵活一些,如果只是使用基本功能的话,官方JDK版本,更健壮。

  • 相关阅读:
    如何开始学习编程? 这 3 步很重要
    php正则表达式验证手机/固定电话/邮箱/身份证/银行卡自定义函数
    【经验分享】-PHP程序员的技能图谱
    PHP程序员的技能图谱
    PHP程序员要掌握的技能
    冒泡排序
    文件下载方法
    加密,解密方法
    获取真实IP
    二维数组根据某个字段排序
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/7689853.html
Copyright © 2011-2022 走看看