一:基本概念
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版本,更健壮。