定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。
jdk当中嵌入了观察者模式以下是简单理解的demo
读者与作者之间 读者作为观察者 作者作为被观察者
public class Reader implements Observer{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Reader(String name) {
this.name = name;
}
//关注
public void subscribe(String writerName){
WriterManager.getInstance().getWriter( writerName ).addObserver( this );
}
//重写通知方法 通知观察者发生的改变
@Override
public void update(Observable o, Object arg) {
if (o instanceof Writer) {
Writer writer = (Writer) o;
System.out.println("优秀的偷窥了"+writer.getName());
}
}
}
//作者 被观察类 继承Observable
public class Writer extends Observable {
//数据名称
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Writer(String name) {
super();
this.name = name;
//添加作者
WriterManager.getInstance().add(this);
}
//作者发布新小说了,要通知所有关注自己的读者
public void addNovel(String novel) {
System.out.println(name + "发布了新书《" + novel + "》!");
setChanged();
notifyObservers();
}
//创建一个类用于对观察者和被观察者进行管理
//管理类
public class WriterManager {
//被观察者列表
private Map <String, Writer> writerMap = new HashMap <String, Writer>();
//添加作者
public void add(Writer writer) {
writerMap.put( writer.getName(), writer );
}
//根据作者姓名获取作者
public Writer getWriter(String name) {
return writerMap.get( name );
}
//单例
private WriterManager() {
}
//作者是单例的
public static WriterManager getInstance() {
return WriterManagerInstance.instance;
}
private static class WriterManagerInstance {
private static WriterManager instance = new WriterManager();
}
}
public class ClientMain {
public static void main(String[] args) {
Writer w1 = new Writer("王八蛋");
Reader reader=new Reader( "张三");
Reader reader1=new Reader( "李四");
reader.subscribe( "王八蛋" );
reader1.subscribe( "王八蛋" );
//七哥和刘能还关注了王小蒙
w1.addNovel( "Message" );
}
}
-------------------------------------------------
运行结果:
王八蛋发布了新书《Message》!
优秀的偷窥了王八蛋
优秀的偷窥了王八蛋
事件驱动
1,观察者模式中观察者的响应理论上讲针对特定的被观察者是唯一的(说理论上唯一的原因是,如果你愿意,你完全可以在update方法里添加一系列的elseif去产生不同的响应,但LZ早就说过,你应该忘掉elseif),而事件驱动则不是,因为我们可以定义自己感兴趣的事情,比如刚才,我们可以监听作者发布新书,我们还可以在监听器接口中定义其它的行为。再比如tomcat中,我们可以监听servletcontext的init动作,也可以监听它的destroy动作。
2,虽然事件驱动模型更加灵活,但也是付出了系统的复杂性作为代价的,因为我们要为每一个事件源定制一个监听器以及事件,这会增加系统的负担,各位看看tomcat中有多少个监听器和事件类就知道了。
3,另外观察者模式要求被观察者继承Observable类,这就意味着如果被观察者原来有父类的话,就需要自己实现被观察者的功能,当然,这一尴尬事情,我们可以使用适配器模式弥补,但也不可避免的造成了观察者模式的局限性。事件驱动中事件源则不需要,因为事件源所维护的监听器列表是给自己定制的,所以无法去制作一个通用的父类去完成这个工作。
4,被观察者传送给观察者的信息是模糊的,比如update中第二个参数,类型是Object,这需要观察者和被观察者之间有约定才可以使用这个参数。而在事件驱动模型中,这些信息是被封装在Event当中的,可以更清楚的告诉监听器,每个信息都是代表的什么。
读者
package com.md.readerAndEvent;
public class Reader implements WriterListener {
private String name;
public Reader(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
//读者可以关注某一位作者,关注则代表把自己加到作者的监听器列表里
public void subscribe(String writerName) {
WriterManager.getInstance().getWriter( writerName ).registerListener( this );
}
//读者可以取消关注某一位作者,取消关注则代表把自己从作者的监听器列表里注销
public void unsubscribe(String writerName) {
WriterManager.getInstance().getWriter( writerName ).unregisterListener( this );
}
@Override
public void addNodel(WritertEvent writerEvent) {
Writers writer = writerEvent.getWriter();
System.out.println( name + "知道" + writer.getName() + "发布了新书《" + writer.getLastNovel() + "》,非要去看!" );
}
}
作者
package com.md.readerAndEvent;
import java.util.HashSet;
import java.util.Set;
public class Writers {
private String name;//作者的名称
private String lastNovel;//记录作者最新发布的小说
private Set <WriterListener> writerListenerList = new HashSet <WriterListener>();//作者类要包含一个自己监听器的列表
public Writers(String name) {
super();
this.name = name;
WriterManager.getInstance().add( this );
}
//作者发布新小说了,要通知所有关注自己的读者
public void addNovel(String novel) {
System.out.println( name + "发布了新书《" + novel + "》!" );
lastNovel = novel;
fireEvent();
}
//触发发布新书的事件,通知所有监听这件事的监听器
private void fireEvent() {
WritertEvent writerEvent = new WritertEvent( this );
for (WriterListener writerListener : writerListenerList) {
writerListener.addNodel( writerEvent );
}
}
//提供给外部注册成为自己的监听器的方法
public void registerListener(WriterListener writerListener) {
writerListenerList.add( writerListener );
}
//提供给外部注销的方法
public void unregisterListener(WriterListener writerListener) {
writerListenerList.remove( writerListener );
}
public String getLastNovel() {
return lastNovel;
}
public String getName() {
return name;
}
}
//自定义监听器
package com.md.readerAndEvent;
import java.util.EventListener;
//自定义监听器
public interface WriterListener extends EventListener {
void addNodel(WritertEvent writerEvent);
}
//作者事件
package com.md.readerAndEvent;
import java.util.EventObject;
//作者事件
public class WritertEvent extends EventObject {
private static final long serialVersionUID = 8546459078247503692L;
public WritertEvent(Object source) {
super( source );
}
public Writers getWriter() {
return (Writers) super.getSource();
}
}
//管理类
package com.md.readerAndEvent;
import com.md.readerAndAutor.Writer;
import java.util.HashMap;
import java.util.Map;
//管理类
public class WriterManager {
private Map <String, Writers> writerMap = new HashMap <String, Writers>();
//添加作者
public void add(Writers writer) {
writerMap.put( writer.getName(), writer );
}
//根据作者姓名获取作者
public Writers getWriter(String name) {
return writerMap.get( name );
}
//单例
private WriterManager() {
}
//作者是单例的
public static WriterManager getInstance() {
return WriterManagerInstance.instance;
}
private static class WriterManagerInstance {
private static WriterManager instance = new WriterManager();
}
}
注
:观察者模式:发布(release)—订阅(subscibe),变化(change)—更新(update)
事件驱动模型:请求(request)—响应(response),事件发生(occur)—事件处理(handle)