今天就来说下我了解的观察者模式。
观察者模式(发布-订阅模式)中存在两种对象,一个是被观察的,即目标(subject),另一个就是观察者(observe)。一个目标可以对应一个观察者:一对多的关系;或者一个目标对应多个观察者,是一对多的关系;也可以出现多个目标对应一个观察者。
观察者模式分为两种:推模式和拉模式。推模式就是目标就观察者需要的那部分数据推送给观察者;而拉模式是目标不知道观察者需要哪部分数据,直接将自己的引用给了观察者。
无论是哪一种模式都需要四个部分组成:目标超类、观察者接口、具体目标类、具体观察者类。下面我们先看看推模式的实现:
Subject
public class Subject {
//注册对应观察者用的List
private ArrayList<Observe> observes = new ArrayList<Observe>();
/**
* 向注册用List里添加observe
* @param observe
*/
public void attachObserve(Observe observe){
observes.add(observe);
}
/**
* 从注册用List中删除指定的observe
* @param observe
*/
public void detach(Observe observe){
observes.remove(observe);
}
protected void notifyObserves(){
for(Observe observe:observes){
observe.update(((ConcreteSubject)this).getState());
}
}
}
Observe
public interface Observe {
public void update(String state);
}
ConcreteSubject
public class ConcreteSubject extends Subject{
//目标状态标记
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
this.notifyObserves();
}
}
ConcreteObserve
public class ConcreteObserve implements Observe{
//观察者状态标记
private String observeState;
@Override
public void update(String state) {
observeState = state;
System.out.println("观察者状态已更新为"+observeState);
}
}
观察者模式(推模式)测试代码
public class ObservePatternTest {
public static void main(String[] args) {
//1.实例化具体目标类
ConcreteSubject subject = new ConcreteSubject();
//2.实例化具体观察者类
ConcreteObserve observe = new ConcreteObserve();
//3.注册观察者
subject.attachObserve(observe);
//4.改变目标状态标记
subject.setState("目标状态改变啦!");
//5.控制台验证观察者状态标记
}
}
拉模式我就不再用具体代码去描述了,简单来说就是将观察者的update方法的参数改为目标的引用就好了。其实拉模式就可以理解为把目标自身扔给了观察者,让观察者自己去取出那些对其有用的信息。这点也是推模式和拉模式的区别所在。
另外,在java源码当中也封装了自己的观察者模式,使用起来相对更简单些
java中的观察者模式是已经把抽象的目标封装为java.util下的Observable类,而观察者则封装为Observe接口。下面看看怎么使用Java的观察这模式。
ConcreteSubject
public class ConcreteSubject extends Observable {
private String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
//下面这句的调用在是用java的观察者模式时必不可少的
this.setChanged();
//使用推模型,
this.notifyObservers(subjectState);
// //使用拉模型
// this.notifyObservers();
}
}
ConcreteObserve
public class ConcreteObserve implements Observer{
private String observeName;
/**
* 第一个参数是目标的对象,采用的是拉模型;第二参数是推模型。
*/
@Override
public void update(Observable o, Object arg) {
//采用推的方式进行状态同步
System.out.println(observeName+"收到了目标的推送:"+arg);
//采用拉的方式进行状态同步
System.out.println(observeName+"收到了消息,主动到目标对象里去寻找:"+((ConcreteSubject)o).getSubjectState());
}
public String getObserveName() {
return observeName;
}
public void setObserveName(String observeName) {
this.observeName = observeName;
}
}
java中的观察者模式测试代码
public class ObservePatternTest {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserve observe = new ConcreteObserve();
observe.setObserveName("cythine");
subject.addObserver(observe);
subject.setSubjectState("明天天气不错!");
}
}
对于观察者模式的使用,精髓就是大家所说的“触发联动”。好吧,就先写这么多,余下的以后再补充。