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版本,更健壮。

  • 相关阅读:
    把git项目放到个人服务器上
    关于fcitx无法切换输入法的问题解决
    博客变迁通知
    (欧拉回路 并查集 别犯傻逼的错了) 7:欧拉回路 OpenJudge 数据结构与算法MOOC / 第七章 图 练习题(Excercise for chapter7 graphs)
    (并查集) HDU 1856 More is better
    (并查集 不太会) HDU 1272 小希的迷宫
    (并查集 注意别再犯傻逼的错了) HDU 1213 How Many Tables
    (最小生成树 Kruskal算法) 51nod 1212 无向图最小生成树
    (并查集) HDU 1232 畅通工程
    (最小生成树 Prim) HDU 1233 还是畅通工程
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/7689853.html
Copyright © 2011-2022 走看看