定义
观察者模式又叫做发布-订阅模式,定义了对象间一对多的依赖关系,使得当对象状态发生变化时,所有依赖它的对象都会收到通知并且自动更新自己。
创建观察者模式的步骤
1、创建目标对象 Subject
功能:目标对象 提供注册(添加)和删除观察者的接口 + 通知变化
一般有attach detach notify 和目标list List<Observer>
拉模型 public void notifyObserver() { for (Observer observer : observers) { observer.updata(this); } } 推模型 public void notifyObserver(String meaage) { for (Observer observer : observers) { observer.updata(meaage); } }
2、创建具体的目标对象 ConcreteSubject
功能:具体的目标对象,负责将有关状态存入到相应的观察者对象中
String subjectState
拉模型 public void setSubjectState(String subjectStatue) { this.subjectState = subjectStatue; this.notifyObserver(); } 推模型 public void setSubjectState(String subjectStatue) { this.subjectState = subjectStatue; this.notifyObserver(subjectStatue); }
3、创建观察者接口 Observe
功能:定义一个更新的接口给那些在目标发生改变的时候被通知的对象
updata(Subject) 传入目标对象,方便获取相应的目标对象的状态 (拉模型)
updata(Message) 传入需要的数据 (推模型)
4、观察者接口的具体实现 ConcreteObserve
功能:实现更新的方法,使自身的状态和目标的状态保持一致
设置String ObserverState = subjectState; updata(Subject) { ObserverState = Subject.subjectState; }
调用观察者模式的步骤
1、创建目标
ConcreteSubject subject = new ConcreteSubject();
2、创建观察者
ConcreteObserve observer1 = new ConcreteObserve(); ConcreteObserve observer2 = new ConcreteObserve();
3、注册观察者到目标函数
subject.atatch(observer1); subject.atatch(observer2);
4、目标发布
subject.setSubjectState(“要发布的数据”);
注意点
-
目标1个 对 多个观察者(也可以多对多,但是要在update内部区分)
-
单向依赖 观察者依赖目标,目标主动通知观察者,观察者被动接收
-
命名建议
-
目标接口 后+subject
-
观察者接口 后+observer
-
观察者更新方法名为update
-
-
触发通知的时机:先改数据后通知
-
通知的顺序:多个观察者之间的顺讯是平行的,没有先后依赖的关系
实现方式
推模型
定义:目标对象主动向观察者推送目标的详细信息,推送的信息通常是目标对象的全部或部分数据
拉模型
定义:目标对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。在实现中会把目标对象通过update方法传递给观察者。
两种模型比较
-
推模型是假定目标对象知道观察者需要的数据;拉模型是目标对象不知道观察者具体需要什么数据,因此把自身传递给观察者,由观察者来取值
-
推模型使观察者对象难以复用;拉模型下,update方法的参数是目标对象本身,基本上可以适应各种情况的需要
javaObserver
Subject
1、class Subject extends Observable 2、public void setContent(String content) { this.content = content; //在使用Java中的observer模式的时候,setChanged必不可少 this.setChanged(); this.notifyObservers(); //拉模型 this.notifyObservers(content); //推模型 }
Observer
1、Observer implements Observer 2、 /** *更新数据 * @param o 拉模型的参数 * @param arg 推模型的参数 */ @Override public void update(Observable o, Object arg) { contetn = ((TestJavaConcreteWeatherSubject)o).getContent();//拉模型 contetn = arg;//推模型 }
优点缺点
优点
1、实现观察者和目标之间的抽象耦合
2、实现动态联动
3、支持广播通信
缺点
1、可能会引起无所谓的操作
何时使用
1、当一个抽象模型有2个方面,其中一个方面的操作依赖于另一个方面的状态变化
2、如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要连带改变
3、当一个对象必须通知其他的对象,但是你又希望这个对象和其他被它通知的对象是松散耦合的