Java中的观察者模式详解
用一个日常中的杂志出版社和杂志订阅者来说明观察者模式是如何工作的。
有n个用户订阅同一类型的某个杂志,比如说读者文摘,用户怎样知道读者文摘更新了呢?用户不可能时刻的去询问杂志出版商读者文摘更新了没有。最好的办法是一旦读者文摘有更新,杂志出版社就向所有的用户提供更新的杂志。用户就可以不用管杂志什么时候更新了。观察者模式也正是这样工作的。在观察者模式中有两个角色一个是观察者也就是上面的杂志订阅者,这里把它定义为:Observer,还有一个杂志出版社我们把它定义为Subject。下面是他们对应的关系:
我们还必须考虑的问题是:可能有新的订阅者订阅杂志,也有的订阅者可能会取消订阅杂志。
下面是类图:
杂志订阅者实现Observer接口,杂志出版社实现Subject接口。
package factoryTest;
import java.util.ArrayList;
import java.util.Date;
interface mySubject {
void notifyObserver(String bookName, Date bookDate);
void removeObserver(myObserver o);
void registerObserver(myObserver o);
void setDetal(String bookName);
}
interface myObserver {
void update(String bookName, Date bookDate);
void display();
}
class Subject1 implements mySubject {
String bookName;
Date bookDate;
ArrayList<Object> observers;
//用于保存所有的订阅者。
public Subject1() {
observers = new ArrayList<Object>();
}
public void setDetal(String bookName) {
// 用于更新信息用。
this.bookDate = new Date();
this.bookName = bookName;
notifyObserver(bookName, bookDate);
//一旦有信息更新就向所有的订阅者提醒。
}
@Override
public void notifyObserver(String bookName, Date bookDate) {
// 如果文摘有信息更新就提醒所有的用户,就跟所有的用户更新信息。
int i = observers.size();
for (int j = 0; j < i; j++) {
((myObserver) observers.get(j)).update(bookName, bookDate);
}
}
@Override
public void removeObserver(myObserver o) {
// 用户取消注册。
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(o);
System.out.println(o.toString() + "has really remove!");
}
}
@Override
public void registerObserver(myObserver o) {
// 用户进行注册。
observers.add(o);
System.out.println(o.getClass().getSimpleName()
+ " has really register!");
}
}
class Observer1 implements myObserver {
String bookName;
Date bookDate;
public Observer1(mySubject mysubject) {
mysubject.registerObserver(this);
}
@Override
public void update(String bookName, Date bookDate) {
this.bookDate = bookDate;
this.bookName = bookName;
display();
}
@Override
public void display() {
System.out.println("bookName:" + bookName + "\n" + "bookDate:"
+ bookDate);
}
}
public class SubjectTest {
public static void main(String[] args) {
Subject1 subject1 = new Subject1();
Observer1 observer = new Observer1(subject1);
//产生一个订阅者,就进行注册。
subject1.setDetal("读者文摘");
}
}
观察者模式对于处理由于一个模块发生变动,因而引起其他多个模块发生变化的时候十分的方便。
比如说,在Java中定义一个会触发多个事件的按钮。一旦点击按钮就会触发多个不同的事件用观察者来实现时很合适的。