文档章节

观察者模式-常用设计模式

dapengking
 dapengking
发布于 2014/03/03 22:19
字数 1250
阅读 601
收藏 7
点赞 0
评论 0

观察者模式

    今天记录下,常用设计模式的第二篇-观察者模式。说起来,我知道观察者模式这个名词,在目前我所知道的设计模式中算是比较早的。因为,在之前闲的时候,曾经自学过android开发,在ui设计中的按钮事件,我印象中就是基于观察者模式实现的。你可以创建一个监听器类的对象,实现当按钮被点击时需要进行的动作。然后将这个对象(其实也就所谓的观察者)注册给按钮。这样,当有鼠标点击按钮时,按钮就会通知所有注册了的监听器类对象,调用其中的事件处理方法。

用headfirst设计模式一书中所说的一句话来概括就是:“当有趣的事情发生时,可千万别错过了!”。

    没错,观察者模式可以帮助对象了解运行现况。不会错过该对象感兴趣的事。而且,对象还可以在运行时决定是否需要继续接受通知。

    再引用一个书中的比方。如果了解报纸的订阅是怎么一回事的话,就会好理解的多。因为它们之间根本就是一样的道理,只是名字不太一样罢了。报纸的出版者就是观察者模式中的“主题(Subject)”,而报纸的订阅者其实也就是我们所谓的“观察者”。

严格的定义:观察者模式定义了对象之间一对多的依赖关系,这样一来,当一个对象改变状态的时候,它的所有依赖对象都可以收到通知并且自动更新状态。

观察者模式的UML类图(图片转自百度图片)

稍微解释下上图的意思:


  1. 首先,遵循面向接口而非面向实现编程的原则,我们需要两个接口:主题(Subject)和观察者(Observer)。在主题接口中声明了一般主题类中最基础的三个方法接口,分别为注册观察者(registerObserver)、删除观察者(removeObserver)和通知观察者(notifyObserver)。而观察者接口中通常至少会声明update方法接口,update将来的实现,用来在观察者收到主题的通知后,作出具体的动作;
  2. 接着,应该实现ConcreteSubject类,并实现Subject接口中的方法。通常情况下,在ConcreteSubject类中会维护一个Observer的容器,用来盛放注册进来的观察者对象的引用;
  3. 最后,当ConcreteSubject类的对象感知到状态改变后,会调用notifyOBserver()方法,在notifyOBserver()的实现中,我们会遍历ConcreteSubject类中Observer的容器中的所有Observer引用,对于每一个引用的对象,调用其update()方法。

通过上面三步的介绍,应该能够比较清楚的理解了观察者模式的基本原理了。在我自己的理解看来,观察者模式,其实与我的上篇帖子中的策略模式的最基本的实现机制相似:也是采用组合的方式,某些对象(这里是观察者对象)的引用组合到某个类(这里指主题类对象)的对象中。当某个事件发生时,主题类对象会采用一定的算法(这个算法不确定,最简单的方式是采用数组作为容器,然后采用遍历数组的方式。)遍历所有的观察者对象引用,并逐一调用update()方法。

与策略模式设计的初衷虽然不同(1.策略模式是为了封装经常变化的逻辑,将经常变动的代码,从比较稳定的代码中剥离出来,从而实现代码复用,并且可以实现在程序运行时的动态组合,提高了程序的灵活性。2.而这里的观察者模式则是为了实现消息的灵活订阅,这种一对多的关系)。但是它们之间在实现上的区别很小,都是通过组合的方式实现的。

一段简单的代码:


package observer;

public interface Subject {

	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObserver();
	
}



package observer;

public interface Observer {
	public void update();
}



package observer;

import java.util.ArrayList;

public class ConcreteSubject implements Subject {

	private ArrayList<Observer> observers = new ArrayList<Observer>();
	
	@Override
	public void notifyObserver() {
		for (Observer observer : observers) {
			observer.update();
		}
	}

	@Override
	public void registerObserver(Observer o) {
		observers.add(o);
	}

	@Override
	public void removeObserver(Observer o) {
		observers.remove(o);
	}

}



package observer;

public class ConcreteObserver implements Observer {

	private String title = null;
	
	public ConcreteObserver(String title,Subject s) {
		this.title = title;
		s.registerObserver(this);
	}

	@Override
	public void update() {
		//观察者收到消息后的处理逻辑
		//
		//
		System.out.println(title + "收到了通知,并且相应了");
	}

}
//测试方法类
package observer;

public class Main {

	public static void main(String[] args) {
		Subject s = new ConcreteSubject();
		
		new ConcreteObserver("observer1",s);
		new ConcreteObserver("observer2",s);
		
		//模拟有事件发生时,调用notifyObserver()方法
		s.notifyObserver();
	}
}




运行结果:


--the end~




© 著作权归作者所有

共有 人打赏支持
dapengking
粉丝 7
博文 133
码字总数 53553
作品 0
东城
程序员
JavaScript设计模式之观察者模式

前言 准备研究一下MVVM的一些东西,由于MVVM运用了观察者模式的思想,因此翻开了《JavaScript设计模式与开发实践》一书,将观察者模式学习了一遍,顺便有对一些常用的设计模式进行一些了解,...

Srtian ⋅ 05/22 ⋅ 0

代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho ⋅ 04/09 ⋅ 0

设计模式之禅(第2版).epub

【下载地址】 本书是设计模式领域公认的3本经典著作之一,“极具趣味,容易理解,但讲解又极为严谨和透彻”是本书的写作风格和方法的最大特点。第1版2010年出版,畅销至今,广受好评,是该领...

winter730 ⋅ 05/16 ⋅ 0

JavaScript 中常见设计模式-代理模式

     代理模式   情景:小明追女生 A   非代理模式:小明 =花=> 女生A   代理模式:小明 =花=> 让女生A的好友B帮忙 =花=> 女生A   代理模式的特点   代理对象和本体对象具有一...

webstack前端栈 ⋅ 06/15 ⋅ 0

系统架构技能之设计模式-单件模式

一、开篇 其实我本来不是打算把系统架构中的一些设计模式单独抽出来讲解的,因为很多的好朋友也比较关注这方面的内容,所以我想通过我理解及平时项目中应用到的一 些常见的设计模式,拿出来给...

wbf961127 ⋅ 2017/11/12 ⋅ 0

JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云 ⋅ 05/18 ⋅ 0

设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu ⋅ 2017/11/02 ⋅ 0

Java经典设计模式-结构型模式-适配器模式(Adapter)

适配器模式 适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的...

Idea ⋅ 01/20 ⋅ 0

设计模式.策略模式

策略模式跟抽象工厂非常相似,基本逻辑是根据需要实例化出需要用的类。不同的是策略模式需要调用者非常清晰的知道有哪些策略,各个策略的调用规则,而抽象工厂的话,需要知道有哪些类,找到调...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

C#设计模式(2)——简单工厂模式

一、引言   这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Day 17 vim简介与一般模式介绍

vim简介 vi和Vim的最大区别就是编辑一个文件时vi不会显示颜色,而Vim会显示颜色。显示颜色更便于用户编辑,凄然功能没有太大的区别 使用 yum install -y vim-enhanced 安装 vim的三种常用模式...

杉下 ⋅ 32分钟前 ⋅ 0

【每天一个JQuery特效】根据可见状态确定是否显示或隐藏元素(3)

效果图示: 主要代码: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>根据可见状态确定 是否显示或隐藏元素</title><script src="js/jquery-3.3.1.min.js" ty......

Rhymo-Wu ⋅ 41分钟前 ⋅ 0

OSChina 周四乱弹 —— 初中我身体就已经垮了,不知道为什么

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @加油东溪少年 :下完这场雨 后弦 《下完这场雨》- 后弦 手机党少年们想听歌,请使劲儿戳(这里) @马丁的代码 :买了日本 日本果然赢了 翻了...

小小编辑 ⋅ 今天 ⋅ 10

浅谈springboot Web模式下的线程安全问题

我们在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,所以并不存在线程安全问题。 由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,...

算法之名 ⋅ 今天 ⋅ 0

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部