责任型模式一:Observer(观察者)模式
目的:
Observer模式的宗旨是在多个对象之间定义一对多的关系,以便当一个对象状态改变时,其他所有依赖于这个对象的对象都能得到通知,并被自动更新。常用于业务逻辑层与表现层的分离。
需求:由GUI引起的

图一
实现图一所示的图形界面。当滑动Slider时,界面中的两个曲线图像需要改变,底部的tPeak显示也需要改变。两个曲线由以下两个公式确定:

最初的模型:
借助于Observer模式,当某个对象发生变化时,关注该对象的其他对象可以被通知。最初的类层次结构如图二。

图二
上图中,ShowBallistics作为表现层元素,包含了burnPanel和thrustPanel这两个BallisticsPanel组件和一个slider滑动条组件,同时由于slider控制前台的显示,ShowBallistics实现了ChangeListener接口并在JSlider组件中注册,当JSlider发生变化时,JSlider依赖注册的ShowBallistics对象调用stateChanged(ChangeEvent e)方法,在该方法中,通过调用burnPanel和thrustPanel对象的setTPeak()方法重画曲线,调用valueLabel (JLabel)的setText()方法刷新显示。
分析这个应用, JSlider值改变引起burnPanel、thrustPanel和valueLabel这三个组件的重刷。根据上面的实现,表现层业务的重刷与业务逻辑层值的改变纠集在一个类当中。这显然是不合适的,简单的,当表现层的需求改变,如不再是画曲线而是画动画,就必须将BallisticsPanel组件改变为其他的显示组件,势必要对ShowBallistics类做出改变。因此我们引入基于Observer的MVC框架实现业务层与表现层的分离,使得两者能够独立变化,也能引起事件的响应。
与Bridge模式类比,以设备驱动为例,Bridge模式将具有一组类似接口的类提升出面向外部应用层调用的接口,实现了驱动具体实现与外部抽象逻辑(怎么用)的分离,方便驱动类的扩展,方便外部逻辑类的自由扩展。所以Bridge模式的关键在扩展,Observer模式的关键在通知。
MVC架构:
综述的,随着应用程序和系统规模的膨胀,必须对责任进行分解和重分解,使每个类保持较小的规模,以便系统维护。
Model/View/Control是将对象与显示它的GUI(View/Control)分离。Java中,基于Observer(观察者)和Observable(被观察者)支持了Observer模式的标准实现。
分析本应用,实际上就是如何得到tPeak并以某几种方式显示tPeak的问题。因此在重构中,首先抽象出模型tPeak,如图三

图三
其中,depend on 关系表示在构造对象是需要传入Tpeak对象。Is Associated with关系表示是成员对象。在模型Tpeak中,当JSlider发生改变时,在stateChange方法中调用Tpeak的setValue方法,实现如下:
- public void setValue(double value) {
- this.value = value;
- setChanged();
- notifyObservers();
- }
可以看到,Tpeak作为Observable,是Observer刷新操作的调用者,作为model,又是前台(JSlider)响应的接收者,可以视为完成了一次从前台到后台再到前台的过程。
对于Observable的底层实现,保持一个Observer的组合,实现一对多的依赖。涉及的操作,无非是增删改查以及触发事件的响应。
- public class Observable {
- private boolean changed = false;
- private Vector obs;
- public Observable() {
- obs = new Vector();
- }
- public synchronized void addObserver(Observer o) {
- if (o == null)
- throw new NullPointerException();
- if (!obs.contains(o)) {
- obs.addElement(o);
- }
- }
- public synchronized void deleteObserver(Observer o) {
- obs.removeElement(o);
- }
- public void notifyObservers() {
- notifyObservers(null);
- }
- 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);
- }
- public synchronized void deleteObservers() {
- obs.removeAllElements();
- }
- protected synchronized void setChanged() {
- changed = true;
- }
- protected synchronized void clearChanged() {
- changed = false;
- }
- public synchronized boolean hasChanged() {
- return changed;
- }
- public synchronized int countObservers() {
- return obs.size();
- }
- }
对于前台的Observer,在构造函数中向对应的Observable进行注册,发生响应时调用update()方法。
- public class BallisticsLabel extends JLabel implements Observer {
- public BallisticsLabel(Tpeak tPeak) {
- tPeak.addObserver(this);
- }
- public void update(Observable obj, Object arg) {
- setText(Format.formatToNPlaces(((Tpeak) obj).getValue(), 2));
- repaint();
- }
- }
责任型模式一:Observer(观察者)模式的更多相关文章
- Java设计模式——Observer(观察者)模式
在多个对象之间建立一对多的关系,以便当一个对象状态改变的时候.其它全部依赖于这个对象的对象都能得到通知,并被自己主动更新. 适用情况: 当一个抽象模型有两个方面,当中一个方面依赖于还有一方面. 将这二 ...
- 设计模式 之 观察者(Observer)模式
观察者(observer)模式定义了一对多的依赖关系,让多个观察者对象能够同时监听某一主题对象.这个主题对象中的状态发生改变时,就会通知所有的观察者对象. 观察者模式的结构图: 结构中各个部分的含义: ...
- 观察者(Observer)模式
http://www.cnblogs.com/zhenyulu/articles/73723.html 一. 观察者(Observer)模式 观察者模式又叫做发布-订阅(Publish/Subscri ...
- 设计模式的征途—15.观察者(Observer)模式
在日常生活中,交通信号灯指挥者日益拥挤的城市交通.红灯亮,汽车停止:绿灯亮,汽车继续前行:在这个过程中,交通信号灯是汽车的观察目标,而汽车则是观察者.随着交通信号灯的变化,汽车的行为也会随之变化,一盏 ...
- 设计模式:观察者(Observer)模式
设计模式:观察者(Observer)模式 一.前言 观察者模式其实最好的名称应该是“发布订阅”模式,和我们现在大数据之中的发布订阅方式比较类似,但是也有区别的地方,在上一个设计模式,我们学习的是仲 ...
- 观察者(Observer)模式 * 委托事件
观察者(Observer)模式:定义了一种一对多的依赖关系.让多个观察者对象同时监听某一个主题对象. 这个主题对象发生变化时会通知所有观察者对象,使他们字段更新自己 /* * 抽象主题(Subje ...
- 行为型模式之Observer模式
观察者模式(又被称为发布-订阅模式.模型-视图模式.源-收听者模式或从属者模式) 观察者模式中,一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知. 应用场景 拍卖会可以认 ...
- ZooKeeper增加Observer部署模式提高性能(转)
除了Leader和Follow模式之外,还有第三种模式:Observer模式. Observer:在不伤害写性能的情况下扩展ZooKeeper. 虽然通过Client直接连接到ZooKeeper集群的 ...
- 设计模式15---观察者模式(Observer Pattern)
一.观察者模式定义 观察者模式定义: Define a one-to-many dependency between objects so that when one object changes s ...
- 学习javascript设计模式之发布-订阅(观察者)模式
1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...
随机推荐
- QString的拼接
QString的append()函数则提供了类似的操作,例如: 1. str = "User: "; 2. str.append(userName); 3. str ...
- 修改分区后的 Grub rescue
声明:这里用到的知识不是原创,综合了几篇教程的成果.找的时候比较混乱,所以来源已经不确定.希望原作者见谅. 系统是Windows 8.1 和 Ubuntu 14.04, Windows是先装的, gr ...
- mysql之 percona-xtrabackup 2.4.7安装(热备工具)
准备:os是centos6.7,提前下载并上传 percona-xtrabackup 安装包,下载网址为: https://www.percona.com/downloads/XtraBackup/L ...
- MySQL 查询数据表里面时间字段为今天添加的计数
一: 下面这条语句查出来的count值 . 查询类型ID(category_id)为18的,今天插入的数据数, created_on: 为数据表中一字段 datetime类型, 记录此条数据添加的时 ...
- PCIE编程1:lspci操作
lspci 是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具. 列出所有的PCIE设备: lspci 选项: -v 使得 lspci 以冗余模式显示所有设备的详细信息. -vv ...
- 蓝桥杯 算法训练 ALGO-124 数字三角形
算法训练 数字三角形 时间限制:1.0s 内存限制:256.0MB 问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和 ...
- 机器学习:集成学习(OOB 和 关于 Bagging 的更多讨论)
一.oob(Out - of - Bag) 定义:放回取样导致一部分样本很有可能没有取到,这部分样本平均大约有 37% ,把这部分没有取到的样本称为 oob 数据集: 根据这种情况,不对数据集进行 t ...
- linux下mysql配置文件my.cnf最详细解释
MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于/etc/my.cnf. 可以查找下:find / -name my.cnf m ...
- ManualResetEvent 用法
第一.简单介绍 ManualResetEvent 允许线程通过发信号互相通信.通常,此通信涉及一个线程在其他线程进行之前必须完成的任务.当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时, ...
- Celery-4.1 用户指南: Routing Tasks (路由任务)
注意: 像主题和扇出之类的路由概念并不对所有传输介质都可用,请翻阅”传输比较表”. 基础 自动路由 路由最简单的方式是使用 task_create_missing_queues 设置(默认启用). 使 ...