1、观察者模式概述
观察者模式运用在一对一或者一对多的对象交互场景,每当一个对象改变时,可以通知其他对象进行改变。观察者模式是“解耦型模式”(降低对象间的耦合度)的最佳范例。
2、观察者模式的结构
先来看一下观察者模式的类图:
观察者模式中主要有以下类:
1. Subject(主题)
知道它的观察者(观察者必须实现了一定的接口),可以有任意多个观察者。
提供注册和注销观察者的接口
2. Observer(观察者)
为那些在主题发生变化时需要获得通知的对象定义一个更新(update)接口。
3. ConcreteSubject(具体主题)
保持实际状态数据,当状态发生变化时通知各观察者
4. ConcreteObserver (具体观察者)
维持一个指向具体主题对象的引用
存储有关状态
实现Observer的更新接口,使自身状态与主题状态保持一致
3、观察者模式示例
下面用一个订阅杂志的例子来展示观察者模式。在订阅杂志后,每当有新杂志进行发布都要讲新杂志发送给每一位订阅者
先来看一下两个接口:
public interface Observer {
void update(String mes);
String getName();
}
public interface Magazine {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
两个接口比较简单,只定义了一些简单的方法,来看一下具体的实现类:
public class ObserverA implements Observer {
private String name;
public ObserverA(String name){this.name = name;}
@Override
public void update(String mes) {
System.out.println("我是" + name + ",收到最新杂志:" + mes + "感谢分享,今天晚上又可以大战三百回合了!" );
}
public String getName() {
return name;
}
}
public class ObserverB implements Observer {
private String name;
public ObserverB(String name){this.name = name;}
@Override
public void update(String mes) {
System.out.println("我是" + name + ",收到最新杂志:" + mes + "感谢分享,今天晚上要嘿嘿嘿~" );
}
public String getName() {
return name;
}
}
public class ObserverC implements Observer {
private String name;
public ObserverC(String name){this.name = name;}
@Override
public void update(String mes) {
System.out.println("我是" + name + ",收到最新杂志:" + mes + ",从今往后我要戒黄赌毒,不要再发信息给我了 !" );
}
public String getName() {
return name;
}
}
在三个观察者实现类中,重写了update()和getName()方法,update()方法中主要存放有杂志更新通知的代码。
再看一下具体主题类,也就是具体杂志类:
import java.util.ArrayList;
import java.util.List;
public class MagazineAV implements Magazine{
private String magazineName;
private ArrayList observers;
public MagazineAV(String name){
this.magazineName = name;
System.out.println("有杂志上新啦:" + magazineName);
observers = new ArrayList();
}
public void setMagazineName(String magazineName) {
System.out.println("有杂志上新啦:" + magazineName);
this.magazineName = magazineName;
}
//注册观察者
@Override
public void registerObserver(Observer o) {
observers.add(o);
System.out.println(o.getName() + "注册成功!");
}
//移除观察者
@Override
public void removeObserver(Observer o) {
observers.remove(o);
System.out.println(o.getName() + "移除成功!");
}
//通知观察者
@Override
public void notifyObservers() {
for (int i = 0 ; i < observers.size(); i++){
Observer observer = (Observer) observers.get(i);
observer.update(magazineName);
}
}
}
可以看出,在具体主题类中,主要是通过数组来存放所有的观察者。我们的添加、移除观察者都是通过对数组的操作来实现的。而我们通知所有的观察者主要是通过遍历这个观察者数组,并且调用观察者自身的update()方法来实现杂志的更新通知。
最后看一下观察者模式的实现:
public static void main(String[] args){
MagazineAV av= new MagazineAV("苍井空");
ObserverA observerA = new ObserverA("光头强");
ObserverB observerB = new ObserverB("金手指");
ObserverC observerC = new ObserverC("施瓦辛格");
av.registerObserver(observerA);
av.registerObserver(observerB);
av.registerObserver(observerC);
av.notifyObservers();
av.removeObserver(observerC);
av.setMagazineName("波多野结衣");
av.notifyObservers();
}
最后的运行结果:
4、总结
观察者模式使得任意数目的观察者不必知道彼此的存在,且主题发生变化时都可以得到主题的通知,而同步改变状态。是一种很松的耦合。具有很好的可重用性。凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
Observer模式的运用场合:
- 一个对象的改变需要同时改变其他对象,但不知道具体有多少其它对象需要改变。
- 一个对象必须通知其他对象,而他又不能预先知道其它对象是谁。