1、本质:触发联动
2、定义:
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
例如:报社的报纸出版时,通知所有的订阅者
3、示意图:
4、特点:
1、目标与观察值之间的关系 --一对多关系
2、单向依赖 --观察者依赖于目标,而目标不依赖于观察者
5、注意:
1、要在状态维护完成后触发通知,否则容易导致观察者与目标对象的状态不一致
2、小心出现相互观察,比如A观察C,C观察A。这样可能会导致死循环
6、推模型和拉模型
1、推模型
目标对象主动向观察者推送目标的详细信息,不管观察者是否需要。
推送的信息通常是目标对象的全部或者部分数据,相当于广播通信
2、拉模型
目标对象通知观察者的时候,只传递少量信息
如果观察者需要更具体的信息,主动到目标对象中获取
目标对象一般把自身作为参数传递给观察者
7、Java中的观察者模式
1、不需要定义观察者和目标的接口,JDK已经定义了
2、目标对象中不再需要维护观察者的注册信息,在Java中的Observable类里面已经实现了
3、触发通知的方式改变,先调用setChanged方法
4、观察者里面,update方法同时支持推模型和拉模型
8、Java中的观察者模式使用示例:
1、目标类
1 public class NewsPaper extends java.util.Observable{ 2 private String content; 3 public String getContent(){ 4 return content; 5 } 6 7 /* 8 * 更新报纸内容,相当于出版报纸 9 */10 public void setContent(String content){11 this.content = content;12 13 //这句话必不可少14 this.setChanged();15 //推方式16 this.notifyObservers(this.content);17 //拉方式18 //this.notifyObservers();19 }20 }
2、观察者类
public class Reader implements java.util.Observer{ private String name; public String getName(){ return name; } public void setName(String name){ this.name = name; } public void update(Observable o, Object obj){ //推方式 System.out.println(name+"收到报纸了,内容是"+obj); //拉方式 System.out.println(name+"收到报纸了,内容是"+((NewsPaper)o).getContent()); }}
备注:Java实现观察者模式默认使用拉模型。 --如果使用推模型,两种方式都能获取到值
3、客户端
public class Client{ public static void main(String[] args){ NewsPaper subject = new NewsPaper(); Reader r1 = new Reader(); r1.setName("张三"); Reader r2 = new Reader(); r2.setName("李四"); Reader r3 = new Reader(); r3.setName("王五"); subject.addObserver(r1); subject.addObserver(r2); subject.addObserver(r3); subject.setContent("本期内容是观察者模式"); }}
9、优点:
1、实现了观察者和目标之间的抽象耦合
2、实现了动态联动
3、支持广播通信
10、缺点:
可能会引起无谓的操作