为了账号安全,请及时绑定邮箱和手机立即绑定
慕课网数字资源数据库体验端
观察者模式_学习笔记_慕课网
为了账号安全,请及时绑定邮箱和手机立即绑定

观察者模式

GerryZhang JAVA开发工程师
难度中级
时长 1小时56分
  • 观察者缺点: 可能会引起无谓的操作: 由于被观察者每次都会进行广播通信,不管观察者是否需要该信息,每个观察者都会被调用update方法.如果观察者不需要执行相应的处理,那么此处操作就浪费了. (浪费的是性能问题,最怕引起误更新,即忘了删除某个观察者,以至于更新了本来不需更新信息的观察者).
    查看全部
    0 采集 收起 来源:观察者优缺点

    2016-04-30

  • 观察者优点: 动态联动就是:做一个操作会引起其他相关操作.
    查看全部
    0 采集 收起 来源:观察者优缺点

    2016-04-30

  • 测试类
    查看全部
  • 具体观察者
    查看全部
  • JAVA提供的对观察者模式的支持 步骤: 1.创建一个具体主题角色类继承Observable类,类中定义一个变量存放具体主题角色的状态信息. 生成set与get方法,通知方法在Observable中已经实现了,在set()方法中调用了setChanged()方法后,根据情况需要选择是否调用带参的notifyObservers方法. 可以使用推模型或拉模型,即当notifyObservers()方法无参时,使用拉模型. 当notifyObservers()方法有参时,则使用推模型. 2.创建一个具体观察者角色类实现Observer接口.Observer接口声明了update(Observable o1,Object o2)方法.Observable类型的参数为了支持拉模型的实现方式,Object类型的参数是为了支持推模型的实现方式. 具体观察者角色类中应定义一个变量存放具体观察者角色的状态信息与存放观察者个人信息的变量,并实现update方法. 3.创建测试类,首先创建一个具体主题角色的对象,创建任意个具体观察者角色对象并初始化个人信息,然后使用具体主题角色继承Observable类的addObserver(Observer o)方法注册观察者.最后调用具体主题角色的set方法更新状态信息. notifyObservers()与notifyObservers(Object obj)方法的区别, notifyObservers()方法内部会调用Observer接口声明的update(Observable obj1 ,Object obj2)方法,把 this当前对象作为update方法的第一个参数,而将第二个参数设置为null. notifyObservers(Object obj)内部也调用Observer接口声明的update方法,并把this当前对象作外update方法的 第一个参数,将notifyObservers方法的参数作为update方法的第二个参数. 所以在Observer接口声明的update方法中都能使用Observale类型的参数,至于update方法中的Object类型参数是否有值 取决于是否使用带参的notifyObservers方法,也就是是否使用推模型.
    查看全部
  • Observable类对notifyObservers()方法进行了重载,即notifyObservers()与notifyObservers(Object arg). 前者用于拉模型,后者用于推模型. 查看notifyObservers(Object arg)源码: public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } 查看notifyObservers()源码: public void notifyObservers() { notifyObservers(null); } 可以看到当使用notifyObservers(Object arg)方法时,即使用推模式,update方法中不仅把arg对象作为参数,而且会把this当前对象作为参数,当使用notifyObservers()方法时,内部直接调用notifyObservers(null),因此update方法有效参数只有this当前对象. 因此两种notifyObservers方法都会把this当前对象作为update()方法的参数,即不管使用哪种模式,在具体观察者中的update方法总可以通过Observable引用获取得到具体主题角色对象.
    查看全部
  • JAVA提供的对观察者模式的支持 在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持. Observable类实现了大部分抽象主题角色的功能,Observable类就相当于抽象主题角色.所有具体主题角色都要继承它. Observer接口中声明了一个update()方法,Java提供的Observer接口就相当于抽象观察者角色. 使用JAVA提供对观察者模式的实现方式与自己实现观察者模式的对比: 1.不需要再定义观察者和被观察者的接口了,JDK帮忙定义了. 2.具体主题角色里面不需要再维护观察者的注册信息了,这个在JAVA中的Observable类里已经实现好了.使用该类定义的addObserver()方法注册观察者(因此通知的顺序是不确定的). 3.触发通知时要先调用Observable类中定义的setChanged()方法,再调用notifyObservers()方法,setChanged()方法是JAVA为了帮助实现更精确的触发控制而提供的功能. 4.具体观察者的实现里面,update()方法能同时支持推模型与拉模型.
    查看全部
  • 观察者实现的两种方式: 在观察者模式中,又分为拉模型和推模型两种方式. 拉模型:主题对象在通知观察者的时候,只传递少量信息.如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据. 一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了. 推模型:主题对象向观察者推送主题的详细信息,不管观察者是否需要.推送的信息通常是主题对象的全部或部分数据. 前面的例子就是典型的拉模型 拉模型: 在抽象观察者声明的update()方法中需要定义抽象具体主题类型的参数. 在具体观察者实现的update()方法中直接通过引用(强转为某个具体主题角色)获取得到某个具体主题角色的状态信息,并赋值给用来存放具体观察者状态的变量. 具体观察者: private String state; public void update(Subject subject){ state=((ConcreteSubject)subject).getSubjectState(); } 抽象主题中的通知观察者方法,不需要传入参数,即抽象主题的通知notify()方法不需要提供参数,因为update()方法中直接使用this关键字传入当前对象. 抽象主题: public void nodifyObservers(){ for(Observer observer : list){ observer.update(this); } } 两种模型比较: 推模型是假定目标对象知道观察者需要的数据. 拉模型是目标对象不知道观察者具体需要什么数据,因此把自身传给观察者,由观察者来取值. 推模型会使观察者难以复用. 拉模型下,update方法的参数是目标对象本身,甚至上可以适应各种情景需要.
    查看全部
  • 堆模型: 在抽象观察者声明的update()方法中,需要提供字符串类型的参数. 在具体观察者实现的update()方法中直接通过参数获取得到某个具体主题角色的状态信息,并赋值给用来存放具体观察者状态的变量. 具体观察者; private String state; public void update(String newState){ state=newState; } 抽象主题中的通知观察者方法,传入的是具体主题的字符串状态信息,因此抽象主题的通知notify()方法中需要提供字符串类型的参数. 抽象主题: public void nodifyObservers(String newState){ for(Observer observer : list){ observer.update(newState); } }
    查看全部
  • 拉模型: 在抽象观察者声明的update()方法中需要定义抽象具体主题类型的参数. 在具体观察者实现的update()方法中直接通过引用(强转为某个具体主题角色)获取得到某个具体主题角色的状态信息,并赋值给用来存放具体观察者状态的变量. 具体观察者: private String state; public void update(Subject subject){ state=((ConcreteSubject)subject).getSubjectState(); } 抽象主题中的通知观察者方法,不需要传入参数,即抽象主题的通知notify()方法不需要提供参数,因为update()方法中直接使用this关键字传入当前对象. 抽象主题: public void nodifyObservers(){ for(Observer observer : list){ observer.update(this); } }
    查看全部
  • 观察者实现的两种方式: 在观察者模式中,又分为拉模型和推模型两种方式. 拉模型:主题对象在通知观察者的时候,只传递少量信息.如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据. 一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了. 推模型:主题对象向观察者推送主题的详细信息,不管观察者是否需要.推送的信息通常是主题对象的全部或部分数据. 前面的例子就是典型的拉模型
    查看全部
  • 观察者模式的调用顺序示意图. List<String> list =new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); for(String str:list){ System.out.println(str); } 运行结果为1 2 3 如果抽象主题使用List集合来注册观察者列表,那么测试类中具体主题实例就会使用List集合来注册观察者,然后当具体主题角色设置状态信息后就会调用notify()方法,方法里循环遍历观察者列表,并进行通知,那么通知的顺序就是注册观察者时的顺序. 如果抽象主题角色使用set、map集合来存储观察者列表,那么测试类中具体主题实例就会使用set或map集合来注册观察者. 当具体主题角色设置状态信息后会通知所有观察者,通知的顺序是不确定的. 如果使用JAVA对观察者模式的支持来实现观察者模式,因为是使用addObserver()方法注册观察者,并不能确定遍历时通知的顺序. 因此观察者实现的功能不能依赖于通知的顺序,也就是多个观察者的通知顺序是平行的,相互不应该有先后依赖的关系.
    查看全部
  • 触发通知Notify()方法的时机. 在实现观察者模式的时候,一般情况下是完成了状态维护后触发通知,因为通知会传递数据(抽象主题循环遍历调用update方法传的参数为this,即传递具体主题角色对象),不能够先通知后改变数据,会导致观察者和具体主题角色的状态不一致.
    查看全部
  • 命名建议: 目标接口的定义,建议在名称后面跟Subject 观察者接口的定义,建议在名称后面跟Observer 观察者接口的更新方法,建议名称为update,不限制参数类型与个数.
    查看全部
  • 具体主题与观察者的关系 具体主题可以只被一个观察者观察(一对一). 一个观察者可以观察多个具体主题(天气与报纸).一般情况下,观察者应为不同的具体主题角色定义不同的update()方法. 单向依赖:只有观察者依赖具体主题角色,而不是具体主题角色依赖观察者.主动权在具体主题角色上.
    查看全部

举报

0/150
提交
取消
课程须知
学习本课程前,需要具备Java基础,面向对象的程序设计思想。如果对这些知识不熟悉,可以学习《Java入门第一季》和《Java入门第二季》这两门课程。
老师告诉你能学到什么?
1、理解观察者模式的概念和结构 2、掌握如何将观察者模式应用到项目中,解决项目实际问题 3、掌握观察者模式的应用场景
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!