很久之前,自己也曾看过一些设计模式的内容,最近在做一些程序代码设计的时,发现忘得差不多了,很多模式也只是有大致影响,决定重新将一些常用的模式复习一下。今天一个模式观察者模式。

观察者模式

观察者模式属于行为模式中的一种;观察者模式定对象一个一对多的依赖关系,让多个观察者对象同时监听同一个主题对象,主题对象在状态发生改变时,通知所有观察者对象使他们能够更新自己。

上面是观察者模式设计类图

  • subject:它是抽象主题的接口,对象通过此接口将自己注册为观察者,或将自己从观察中者删除

  • ConcreteSubject:一个实现主题接口的具体主题,除了实现注册和删除的方法外,它还有一个change方法,用来在状态改变时通知所有观察者

  • Observer:观察者接口,所有具体的观察者都实现此接口

  • ConcreteObserver:具体的观察者

package com.mtx.demo.observer;import java.util.ArrayList;
import java.util.List;public abstract class Subject {// 保存注册的观察者对象private List<Observer> list = new ArrayList<Observer>();// 注册观察者对象public void attach(Observer observer) {list.add(observer);System.out.println("添加新的观察者");}// 删除观察者对象public void detach(Observer observer) {list.remove(observer);System.out.println("删除一个观察者");}// 通知所有注册的观察者对象public void nodifyObservers(String newState) {for (Observer observer : list) {observer.update(newState);}}
}
复制代码

一个具体主题

package com.mtx.demo.observer;public class ConcreteSubject extends Subject {private String state;public String getState() {return state;}// 状态发生改变,通知各个观察者public void change(String newState) {state = newState;this.nodifyObservers(state);}
}
复制代码

抽象的观察者

package com.mtx.demo.observer;public interface Observer {// 更新接口public void update(String state);
}
复制代码

一个具体观察者

package com.mtx.demo.observer;public class ConcreteObserver implements Observer {private String observerState;@Overridepublic void update(String state) {observerState = state;System.out.println("观察者状态跟新了:" + observerState);}
}
复制代码

客户端中,我们创建一个具体主题对象,在创建一个观察者对象,之后将观察注册到主题对象像上,这样当主题对象的状态改变时,所有的观察者对象都会收到通知,改变自己的状态。

package com.mtx.demo.observer;public class Client {public static void main(String[] args) {// 创建主题对象ConcreteSubject subject = new ConcreteSubject();// 创建观察者对象Observer observer = new ConcreteObserver();// 将观察者对象登记到主题对象上subject.attach(observer);// 改变主题对象的状态subject.change("有新的技术博客了");}}
复制代码

运行代码结果如下

问题

  • 观察者模式中一对多是如何体现的

主题是一个具有状态的对象,而多个观察者可以使用这个主题的状态,多个观察者依赖主题对象来告诉他们这些状态何时改变,这就产生了一个主题对应多观察者的关系

  • 观察者模式是松如何做到耦合的

主题只知道观察者实现了某一个接口(Observer接口),主题不用知道观察者具体是谁,做了哪些操作等,任何时候我们都可以添加新的观察者,那是因为主题唯一依赖的是一个观察者的Observer接口的对象列表,因此我们可以随时添加观察者,有新的主题出现时主题代码不用修改。

推模型和拉模型。

  • 推模型:主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据,刚才上面的例子就是一个推模型。

推模型会是观察者难以复用,因为每个观察者的updata方法的参数可能不同,数据量非常大的时候推模型不适合

  • 拉模型:主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

另外Java语言提供的对观察者模式的支持,在java.util包中,提供了一个Observable类以及一个Observer接口

  • 优点:

1.在观察者和被观察者之间建立一个抽象的耦合;

2.支持广播通信

  • 缺点:

1.如果一个被观察者对象有很多观察者,将所有观察者通知到会花费很多时间;

2.如果在被观察者之间有循环依赖,被观察者会触发他们之间的循环调用,导致系统崩溃;

3.观察者没有相应的方式使其知道所观察的对象时怎么发生变化的。

参考:Head First 设计模式

Java 设计模式之《观察者模式》相关推荐

  1. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  2. Java设计模式(三) -- 代理模式

    代理是一种设计模式,即通过代理对象访问目标对象,这样可以在目标对象实现的基础上,增强额外的功能,即扩展目标类的功能. 通常编程中存在一种思想,即不要随意修改别人的代码或者方法,所以代理就可以在不修改目 ...

  3. java设计模式之代理模式详解

    代理模式在Java中十分常见,有如Spring实现AOP而使用动态代理,更有RPC实现中使用的调用端调用的代理服务.代理模型除了是一种设计模式之外,它更是一种思维,所以探讨并深入理解这种模型是非常有必 ...

  4. java设计模式之代理模式多种写法(三)

    背景 代理模式属于结构型模式,代理模式也是我们开发中常用的设计模式之一,本次讲解以下几种代理模式的写法,希望可以帮助大家更快的理解代理模式,包括自己写一个动态代理的方法. 静态代理 package c ...

  5. Java设计模式之代理模式(Proxy)

    参考http://blog.csdn.net/jianghuxiaoxiami/article/details/3403924 1.代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的 ...

  6. Java设计模式-Proxy代理模式

    问题分析: 什么是代理模式呢?其实我们在生活中并不少见.对于程序员来说最常接触的莫过于代理上网了,连接大力服务器地址,就可以访问网络. 还有每天吃饭赶进度是常事,叫公司的同事帮忙带饭也是一种代理:如果 ...

  7. Java 设计模式之代理模式

    1.静态代理 被代理对象和代理对象都要实现相同的接口或者继承相同的父类. 不需要修改被代理对象就可以实现对功能的扩展,缺点是如果接口发生变化,比如增加新方法,被代理对象和代理对象都需要维护. 1)首先 ...

  8. java设计模式之——代理模式

    1,什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 2,策略模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象 ...

  9. Java设计模式之代理模式

    示例为最经典的西门庆示例 1,什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 2,策略模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理 ...

  10. Java设计模式-之代理模式(动态代理)

    一.简介 1.什么叫代理模式:        简而言之就是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

最新文章

  1. DIV+CSS圆角边框
  2. 信号完整性与电源完整性分析_「1月11日 免费视频直播」高速PCB信号完整性和电源完整性仿真实战分析、ADS创新解决方案分享-送给工程师的一份新年礼物...
  3. 后退键无效 html,javascript – Cordova – window.history.back()不支持iOS 9中的HTML后退按钮...
  4. eclipse导入github项目提示没有发现项目_eclipse clone克隆github远程库工程到本地
  5. 2Boost之UPD,Client and Server
  6. 【Task5(2天)】模型调参
  7. 如何删除Github上一个pull request
  8. PHP笔记-自定义MVC框架
  9. thinkphp mysql高并发_WBB - ThinkPhp高并发提交如何保障数据正常
  10. python3的面向对象_python3学习之面向对象
  11. php-open网站还可以用,nginx+php使用open_basedir限制站点目录防止跨站
  12. 个人Androidstudio快捷键及常用设置配置
  13. c程序设计语言如何补零,C语言程序设计(补)-中国大学mooc-题库零氪
  14. DelayedWorkQueue踩坑笔记
  15. extjs 调用金税COM接口
  16. TrinityCore魔兽世界服务器-环境搭建(Debian11)
  17. 【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
  18. 深度学习花朵识别系统的设计与实现
  19. 交互式多模型算法IMM——机动目标跟踪中的应用
  20. mysql的cpu使用率突然增高_mysql cpu使用率过高解决方法

热门文章

  1. vim 语法高亮显示
  2. 如何让Linux禁止Ctrl+Alt+Del重启(防止被强行关闭)     erikxue 薛忠权
  3. ubuntu系统初始化
  4. MySQL 性能优化,优化设计及设计原则解读
  5. 解决python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX
  6. jQ进阶篇--jQuery封装placeholder效果,让低版本浏览器支持该效果
  7. 宽带服务价值链之:ISP,ICP,ASP,IDC,CDN
  8. asp.net中使用窗体身份验证
  9. 我也来说一下SilverLight3的ChildWindow--带Logo的标题
  10. SolrCloud在linux上的搭建