简介
观察者模式又称为发布/订阅(Publish/Subscribe)模式,观察者模式中有主题(Subject)和观察者(Observer),分别对应报社和订阅用户(你).
观察者模式定义了对象之间的一对多的依赖关系,这样,当”一”的一方状态发生变化时,它所依赖的”多”的一方都会收到通知并且自动更新。
观察者模式所涉及的角色有:
- 抽象主题(Subject)角色:即抽象被观察者(Observable)角色。抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
- 具体主题(ConcreteSubject)角色:即具体被观察者(Concrete Observable)角色。将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
- 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
- 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
简单实现
一个简单例子,教师布置作业。
抽象主题(Subject)角色:
具体主题(ConcreteSubject)角色:
抽象观察者(Observer)角色:
具体观察者(ConcreteObserver)角色:
java内置的观察者模式
在java.util包中包含有基本的Observer接口和Observable抽象类.
使对象变为观察者
实现观察者接口(java.util.Observer),然后调用Observable对象的addObserver()方法.不想再当观察者时,调用deleteObserver()就可以了
被观察者(主题)发出通知
- 第一步:先调用setChanged()方法,标识状态已经改变的事实.
- 第二步:调用notifyObservers()方法或者notifyObservers(Object arg),这就牵扯到推(push)和拉(pull)的方式传送数据.
如果想用push的方式”推”数据给观察者,可以把数据当做数据对象传送给notifyObservers(Object arg)方法,其中的arg可以为任意对象,意思是你可以将任意对象传送给每一个观察者.
如果调用不带参数的notifyObserver()方法,则意味着你要使用pull的方式去主题对象中”拉”来所需要的数据.123456789101112131415public class TeacherSubject extends Observable {private String info;public void setHomework(String info) {this.info = info;System.out.println("老师布置" + info);setChanged();notifyObservers(info);}public String getInfo() {return info;}}
观察者如何接收通知
观察者只需要实现一个update(Observable o,Object arg)方法,第一个参数o,是指定通知是由哪个主题下达的,第二个参数arg就是上面notifyObserver(Object arg)里传入的数据,如果不传该值,arg为null
总结
观察者模式提供了一种对象设计,让主题和观察者之间耦合度降得很低(大部分设计模式都是为了解耦)。
关于观察者的一切,主题只知道观察者实现了Observer接口,并不需要观察者具体的类是谁,做了什么或者其他细节。
这样的话,由于松耦合,改变主题或者观察者其中一方,并不会影响另一方,只要他们之间的接口仍被遵守,就可以自由地改变它。