观察者模式的结构
观察者模式所涉及的角色有:
● 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
● 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
● 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
● 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用
总结
一. 观察者模式定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅模式、模型-视图模式、源-监听器模式或从属者模式。观察者模式是一种对象行为型模式。
二 . 观察者模式包含四个角色:目标又称为主题,它是指被观察的对象;具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;观察者将对观察目标的改变做出反应;在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。
三.观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
四.观察者模式的主要优点在于可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立一个抽象的耦合,支持广播通信;其主要缺点在于如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,而且如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
五.观察者模式适用情况包括:一个抽象模型有两个方面,其中一个方面依赖于另一个方面;一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变;一个对象必须通知其他对象,而并不知道这些对象是谁;需要在系统中创建一个触发链。
六.在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了Java语言对观察者模式的支持。
实例
1.继承Observable和实现Observer接口
被观察者类subject实现:被观察者类实现两个类,一个是setChanged(),另一个是notifyObservers()。第一方法setChanged()被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。
package observerpattern;
/**
* 官方引例
*/
import java.util.Observable;
/**
* 被观察者
* @author Administrator
*
*/
public class Subject extends Observable{
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
/**
* Marks this <tt>Observable</tt> object as having been changed; the
* <tt>hasChanged</tt> method will now return <tt>true</tt>.
* 标记此可观察对象已被更改;
改变了方法将返回true。
*/
this.setChanged();
/**
* 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>
*
* 如果该对象已更改,如
*改变了方法,然后通知所有的观察者
*然后调用clearchanged方法
*指示此对象已不再更改。
*> >
*每个观察者有其更新方法称为两个
*参数:这个可观察对象和空。在其他
*字,此方法相当于:
* < blockquote > <它>
* notifyobservers(空)< > < /传达/ TT
*/
this.notifyObservers();
this.addObserver(null);
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
this.setChanged();
this.notifyObservers();
}
@Override
public String toString() {
return "Subject [name=" + name + ", sex=" + sex + "]";
}
}
观察者类实现:实现update()方法,当被观察者对象的状态发生变化时,被观察者对象的notifyObservers()方法就会调用这一方法
package observerpattern;
import java.util.Observable;
/**
* 观察者
* @author Administrator
*
*/
public class Observer implements java.util.Observer {
// public void update( ){
// //System.out.println("我是观察者");
// }
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
System.out.println("我是观察者");
}
}
实例二:被观察者类(publisher)
package observerpattern;
/**
* 观察者模式事例
*/
import java.util.ArrayList;
import java.util.List;
import java.util.Observer;
//Subject
public class Publisher {
List<reader> readList = new ArrayList<reader>();
/**
* 添加观察者
* @param reader
*/
public void addReader(reader reader){
readList.add(reader);
}
/*
* 删除观察者
*/
public void deleteReader(int index){
readList.remove(index);
}
/*
* 发通知
*/
public void notifyReader(String string){
/*
* foreach的语句格式:
for(元素类型t 元素变量x : 遍历对象obj){
引用了x的java语句;
}
*/
for (reader read : readList) {
read.update(string);
}
}
}
------------------------------------------------------------------------------------------------------------
子类
package observerpattern;
public class PublisherMan extends Publisher{
@Override
public void notifyReader(String string) {
// TODO Auto-generated method stub
super.notifyReader(string);
}
}
观察者类:reader接口类
package observerpattern;
public interface reader {
public void update();
public void update(String str);
}
------------------------------------------------------------------------------------------------------------
子类
package observerpattern;
public class readerWoman implements reader{
@Override
public void update() {
// TODO Auto-generated method stub
}
@Override
public void update(String str) {
// TODO Auto-generated method stub
System.out.println("新内容:" +str);
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------
main
package observerpattern;
public class MainClass {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer =new Observer();
Observer observer1 =new Observer();
subject.addObserver(observer);
subject.addObserver(observer1);
int total = subject.countObservers();
System.out.println(total);
subject.setName("haha");
subject.setSex("男");
//subject.toString();
//
// PublisherMan pMan = new PublisherMan();
// readerWoman woman = new readerWoman();
// pMan.addReader(woman);
//
// pMan.notifyReader("我的第一篇博客发布了,大家快来看吧");
}
}
----------------------------------------------------------------------------------------------------------------------------------------------------
例一运行结果:
2
我是观察者
我是观察者
我是观察者
我是观察者
例二运行结果:
新内容:我的第一篇博客发布了,大家快来看吧