观察者模式(Observer)
Posted Archibald Witwicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式(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版本,更健壮。
以上是关于观察者模式(Observer)的主要内容,如果未能解决你的问题,请参考以下文章
[Android&Java]浅谈设计模式-代码篇:观察者模式Observer
JDK自带的Observable和Observer实现观察者模式