描述
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,也称发布-订阅(Publish/Subscribe)模式,这是一种行为型模式(Behavioral),主要用于描述类或对象怎样交互以及怎样分配职责。观察者模式中通常包括观察目标和观察者两个继承层次结构,可实现观察者和目标之间的抽象耦合,同时实现了对象之间的动态联动。
文字太抽象?可以先不管,直接往下看案例,回过头来再看定义,就很简单了:
场景举例
通过学校放学打铃,所有在校人员听到后,做出反应,可以比较形象的理解观察者模式,如下图:
观察者模式在类设计的时候会用到四个内容:
代码案例
案例源码
https://gitee.com/sujianfeng/design-pattern
被观察者抽象类:学校铃声
public abstract class AbstractSchoolBell {
/**
* 增加观察者
* @param schoolPerson 入校人员
*/
abstract void attach(AbstractSchoolPerson schoolPerson);
/**
* 剔除观察者
* @param schoolPerson 离校人员
*/
abstract void detach(AbstractSchoolPerson schoolPerson);
/**
* 广播通知(铃声)
*/
abstract void notifyBell();
}
被观察者:放学铃声
public class LeveSchoolBell extends AbstractSchoolBell {
private List<AbstractSchoolPerson> schoolPersonList = new ArrayList<>();
@Override
public void attach(AbstractSchoolPerson schoolPerson) {
schoolPersonList.add(schoolPerson);
}
@Override
public void detach(AbstractSchoolPerson schoolPerson) {
schoolPersonList.remove(schoolPerson);
}
@Override
public void notifyBell() {
//广播通知所有在校人员
for (AbstractSchoolPerson schoolPerson : schoolPersonList){
schoolPerson.listenBell(this);
}
}
}
观察者抽象类:在校人员
public abstract class AbstractSchoolPerson {
/**
* 监听铃声
*/
abstract void listenBell(AbstractSchoolBell abstractSchoolBell);
}
观察者:学生
public class Student extends AbstractSchoolPerson {
@Override
public void listenBell(AbstractSchoolBell schoolBell) {
System.out.println("收拾书包!");
}
}
观察者:老师
public class Teacher extends AbstractSchoolPerson {
@Override
public void listenBell(AbstractSchoolBell schoolBell) {
System.out.println("收拾教案!");
}
}
观察者:门卫
public class Guard extends AbstractSchoolPerson {
@Override
public void listenBell(AbstractSchoolBell schoolBell) {
System.out.println("打开学校大门!");
}
}
单元测试
public class ObserverTest {
@Test
public void test(){
//放学铃声
LeveSchoolBell leveSchoolBell = new LeveSchoolBell();
//学生
Student student = new Student();
//老师
Teacher teacher = new Teacher();
//门卫
Guard guard = new Guard();
//学校人员
leveSchoolBell.attach(student);
leveSchoolBell.attach(teacher);
leveSchoolBell.attach(guard);
//下课铃声响了
leveSchoolBell.notifyBell();
}
}
Java自带的观察者模式
在java.util包中包含有基本的Observer接口和Observable抽象类.功能上和SchoolBell 接口和SchoolPerson 接口类似.不过在使用上,就方便多了,因为许多功能比如说注册,删除,通知观察者的那些功能已经内置好了。使用javaAPI的观察者模式需要明白这么几件事情:
如何使对象变为观察者?
实现观察者接口(java.util.Observer),然后调用Observable对象的addObserver()方法.不想再当观察者时,调用deleteObserver()就可以了.
被观察者(主题)如何发出通知?
第一步:先调用setChanged()方法,标识状态已经改变的事实.
第二步:调用notifyObservers()方法或者notifyObservers(Object arg),这就牵扯到推(push)和拉(pull)的方式传送数据.如果想用push的方式"推"数据给观察者,可以把数据当做数据对象传送给notifyObservers(Object arg)方法,其中的arg可以为任意对象,意思是你可以将任意对象传送给每一个观察者.如果调用不带参数的notifyObserver()方法,则意味着你要使用pull的方式去主题对象中"拉"来所需要的数据.
观察者如何接收通知?
观察者只需要实现一个update(Observable o,Object arg)方法,第一个参数o,是指定通知是由哪个主题下达的,第二个参数arg就是上面notifyObserver(Object arg)里传入的数据,如果不传该值,arg为null.
思考
观察者模式的意义是什么?观察者模式比较简单,大家理解后,就可以很轻松的回答这个问题,这里就不写了,留给大家自己总结。