观察者模式又称为发布订阅模式,是对象的行为模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监视着被观察者的状态,当被观察者的状态发生变化时,会通知所有的观察者,并让其自动更新自己。
那这里我用一个老师和课代表的例子来客观的表示观察者模式。
例如:老师有很多的作业,他会分别告诉各科的课代表,每当有新作业时,就会把这个作业告诉对应的课代表,于是就有了这样的伪代码:
if(老师有新作业了){
告诉语文课代表语文作业;
告诉数学课代表数学作业;
}
如果作业很多的情况的话,那就需要改变这段伪代码:
if(老师有新作业了){
告诉语文课代表语文作业;
告诉数学课代表数学作业;
告诉英语课代表英语作业;
告诉物理课代表物理作业;
告诉化学课代表化学作业;
}
按照这样的方法,如果还有其他科目的作业,那么还要继续在if里面添加逻辑。首先,如果多达十几门学科,那么id语句的逻辑就会异常复杂了。这样代码耦合就会增加很多,其次,这样会在if语句里堆积太多的代码,不利于维护,同时造成扩展困难。
而观察者模式更易于扩展,责任也更加清晰。首先,把每一个课代表看成一个观察者,每个观察者都能观察到作业列表(被监听对象)。当老师发布了新作业时,就会发送到这个作业列表上,于是作业列表(被监听对象)发生了变化,这时就可以出发各个课代表接口(观察者)发送新作业到对应的课代表那里。观察者模式示例如下图所示:
类似于这样,一个对象(课代表接口)会去监听另外一个对象(作业列表),当被监听对象(作业列表)发生变化时,对象(课代表接口)就会触发一定的行为,以适合变化的逻辑模式,我们称之为逻辑模式,课代表接口被称为观察者或者监听者,作业列表被称为被观察者或者被监听者。
下面我用一个代码实例来展示观察者模式。
观察者模式要同时存在观察者和被观察者双方,观察者可以是多个。在Java中,需要去继承java.util.Observable类,先看被观察者——一个作业列表,代码如下所示:
ZuoyeList.java
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class ZuoyeList extends Observable{
private List<String> ZuoyeList=null; //作业列表
private static ZuoyeList instance; //类唯一实例
//构建方法私有化
private ZuoyeList() {
}
/**
* 取得唯一实例
* @return 作业列表唯一实例
*/
public static ZuoyeList getInstance() {
if(instance==null) {
instance=new ZuoyeList();
instance.ZuoyeList=new ArrayList<String>();
}
return instance;
}
/**
* 增加观察者(课代表接口)
* @param observer 观察者
*/
public void addZuoyeListObserver(Observer observer) {
this.addObserver(observer);
}
/**
* 新增产品
* @param newZuoye 新作业
*/
public void addZuoye(String newZuoye) {
ZuoyeList.add(newZuoye);
System.out.println("作业列表新增加了作业:"+newZuoye);
this.setChanged(); //设置被观察者对象发生了变化
this.notifyObservers(newZuoye); //通知观察者,并传递新作业
}
}
这个类的一些基本内容和主要方法如下:
- 构造方法私有化,避免通过new的方式去创建对象,而是通过getInstance方法获得作业列表单例。
- addZuoyeListObserver方法可以增加一个作业接口(观察者)。
- 核心逻辑在addZuoye方法上。在作业列表上增加一个新作业,然后调用setChanged方法。这个setChanged方法用于告知观察者当前被观察者发生了变化,如果没有,则无法触发其行为。最后通过notifyObservers告知观察者,让它们发生相应的动作,并将新作业作为参数传递给观察者。
这时已经有了被观察对象,还要去编写观察者。仍以语文课代表和数学课代表为例,去实现它们的作业接口。作为观察者需要实现java.util.Observer接口的update方法,代码如下:
YuwenObserver.java
import java.util.Observable;
import java.util.Observer;
public class YuwenObserver implements Observer{
@Override
public void update(Observable o, Object zuoye) {
// TODO Auto-generated method stub
String newZuoye=(String) zuoye;
System.out.println("发送新作业【"+newZuoye+"】同步到语文课代表");
}
}
ShuxueObserver.java
import java.util.Observable;
import java.util.Observer;
public class ShuxueObserver implements Observer{
@Override
public void update(Observable o, Object zuoye) {
// TODO Auto-generated method stub
String newZuoye=(String) zuoye;
System.out.println("发送新作业【"+newZuoye+"】同步到数学课代表");
}
}
测试代码:
test.java
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ZuoyeList observable=ZuoyeList.getInstance();
YuwenObserver yuwwenObserver=new YuwenObserver();
ShuxueObserver shuxueObserver=new ShuxueObserver();
observable.addObserver(yuwwenObserver);
observable.addObserver(shuxueObserver);
observable.addZuoye("新作业123");
}
}
运行结果: