文档章节

观察者(Observer)模式

叶知秋
 叶知秋
发布于 2013/08/15 22:26
字数 1671
阅读 57
收藏 0
点赞 0
评论 0

       观察者模式是对象的行为模式,又叫发布-订阅模式、模型-视图模式、源-监听模式、或从属者模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有的观察者对象,使它们能够自己更新自己。
       一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其他的对象做出相应的改变。能做到这一点的设计方案很多,但是为了使系统易于复用,应该选用低耦合度的设计方案。减少对象之间的耦合有助于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行为的协调一致,保证高度的协作。观测者模式是满足这一要求的各种设计方案中最重要的一种。
     
观察者模式的结构
      
下图是一个简单的示意性实现类图:
                                         
           观察者模式的静态结构可以从类图中看出,在这个观察者模式的实现中,有以下角色:
      (1)抽象主题(Subject)角色:主题角色把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。
      (2)抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。
      (3)具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observer)。具体主题角色通常用一个具体子类实现。
      (4)具体观察者(ConcreteObserver)角色:存储于主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。 
       在类图中,从具体主题角色指向抽象观察者角色的合成关系,代表具体主题对象可以包含任意多个对抽象观察者对象的引用。由于java的抽象类是不可能有实例的,因此这些引用的的真实类型必定是ConcreteObserver类型,而这些引用的静态类型是Observer类型,这意味着主题对象不需要知道引用了哪些ConcreteObserver类型,而只知道抽象Observer类型,这就使得具体主题对象可以动态的维护一系列的对观察者对象的引用,并且在需要的时候调用每一个观察者的公有的update()方法。
       下面给出示意性代码:
 1.ject.java

package com.pattem.behavioral.Observer;

/**
 * 抽象主题角色
 * */
public interface Subject {
	
	//登记一个新的观察者对象
	public void attach(Observer observer);
	
	//删除一个已经登记过的观察者对象
	public void detach(Observer observer);
	
	//通知所有登记过的观察者对象
	public void notifyObserver();

}

2.ConcreteSubject.java

package com.pattem.behavioral.Observer;

import java.util.Enumeration;
import java.util.Vector;

import javax.sound.sampled.EnumControl;

public class ConcreteSubject implements Subject{

	private Vector<Observer> observersVector = new Vector<Observer>();
	
	public void attach(Observer observer) {
		observersVector.addElement(observer);
	}

	public void detach(Observer observer) {
		observersVector.removeElement(observer);
	}
	
	public void notifyObserver() {
		Enumeration enumeration = observers();
		while(enumeration.hasMoreElements()){
			((Observer)enumeration.nextElement()).update();
		}
	}
	
	public Enumeration observers(){
		return ((Vector)observersVector.clone()).elements();
	}

}

3.Observer.java

package com.pattem.behavioral.Observer;

/**
 * 抽象观察者角色
 * */
public interface Observer {
	
	//调用这个方法更新自己
	void update();

}

4.ConcreteObserver.java

package com.pattem.behavioral.Observer;

/**
 * 具体观察者角色
 * */
public class ConcreteObserver implements Observer{

	public void update() {
		
		//修改方法
		System.out.println("I am notified");
	}
}

         如果仔细考察主题功能的对象的功能时,可以发现它必须使用一个java集合来维护一个对所有的观察者对象的引用。而在前面所给出的实现里面,管理这个集合的方法是由抽象主题角色声明并由具体主题角色实现的。这才导致了类图中从具体主题角色到抽象观察者角色的连线。
       但是一个自然的问题就是,这些集合管理方法难道在每一个具体主题角色中都不同吗?答案是否定的。在大多数情况下,这些集合管理方法本身就是所有具体主题角色所共有的,因此这些方法连同集合本身都可以移动到抽象主题角色中去。同意由于notifyObserver()方法依赖集合对象,也可以移到抽象主题角色中去。  这就是第二种实现方案。其结构类图如下:   
                           
       下面给出抽象主题的源码:
Subject.java

package com.pattem.behavioral.Observer2;

import java.util.Enumeration;
import java.util.Vector;


/**
 * 抽象主题角色
 * */
public abstract class Subject {
	
	//保存对观察者对象的引用
	private Vector<Object> observerVector = new Vector<Object>();
	
	//登记一个新的观察者对象
	public void attach(Observer observer){
		observerVector.addElement(observer);
		System.out.println("Attach an observer");
	}

	//删除一个已经登记过的观察者对象
	public void detach(Observer observer){
		observerVector.removeElement(observer);
	}
	
	public void notifyObserver(){
		Enumeration<Object> enumeration = observers();
		while(enumeration.hasMoreElements()){
			((Observer)enumeration.nextElement()).update();
		}
	}
	//给出观察者聚集的 Enumeration对象
	public Enumeration<Object> observers(){
		return ((Vector)observerVector.clone()).elements();
	}
}

ConcreteSubject.java

package com.pattem.behavioral.Observer2;


/**
 * 具体主题角色
 * */
public class ConcreteSubject extends Subject {

	private String state;
	
	public void change(String state){
		this.state = state;
		this.notifyObserver();
	}
}

Client.java

package com.pattem.behavioral.Observer2;

/**
 * 客户端代码 Client
 * */
public class Client {
	
	private static ConcreteSubject subject;
	private static Observer observer;
	
	public static void main(String[] args) {
		
		//创建主题对象
		subject = new ConcreteSubject();
		//创建观察者对象
		observer = new ConcreteObserver();
		//将观察者对象登记到
		subject.attach(observer);
		//改变主题对象的状态
		subject.change("new state");
	}
}

     在运行时,这个客户端首先创建了具体主题类的实例,以及一个观察对象,然后它调用主题对象的attach()方法,将这个观察者对象向主题对象登记,也就是将它加入到主题对象的集合中去。



java语言提供对观察者模式的支持

     
在java语言的java.util库里面,提供了一个Observable的类和一个Observer的接口,构成java语言对观察者模式的支持。(详情,请参考java.util.Observable 类源码)

© 著作权归作者所有

共有 人打赏支持
叶知秋
粉丝 24
博文 78
码字总数 103570
作品 0
浦东
程序员
设计模式17——Observer设计模式

Observer观察者设计模式用于将对象的变化通知给感兴趣的用户。在Observer模式中的角色为主题(subject)与观察者(observer),观察者订阅它感兴趣的主题,一个主题可以被多个观 察者订阅,当...

小米米儿小 ⋅ 2014/01/26 ⋅ 0

[转]Java实现观察者模式

观察者模式简介: 定义:定义对象间的一对多的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。 原理:由四部分组成抽象目标类,具体目标类,抽象观察者类,具...

inferrrrrr ⋅ 2009/11/03 ⋅ 0

【设计模式系列】浅析观察者模式

观察者<Observer>模式(有时又被称为发布-订阅<Publish/Subscribe>模式、模型-视图<Model/View>模式、源-收听者<Source/Listener>模式或从属者<Dependents>模式)是软件设计模式的一种。在此......

磊神Ray ⋅ 2011/10/18 ⋅ 0

Java程序员从笨鸟到菜鸟之(三十六)大话设计模式(六)观察者模式

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188 Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对...

长平狐 ⋅ 2012/11/12 ⋅ 0

设计模式--观察者模式

观察者模式(observer): 示例: 观察者模式测试类ObserverTest.java 主题接口类Subject.java 观察者接口类Observer.java 猎头类HeadHunterImpl.java 求职者类JobSeekerImpl.java...

有钱有爱 ⋅ 2016/04/09 ⋅ 0

iOS-观察者模式

前言 与其说发布订阅是观察者模式的别名,还不如说发布订阅本质上是一种特殊的观察者模式;两种模式都主要是用于解除一个对象与多个对象之间的耦合,即不管有多少个监听者(observer),都不...

麦兜卖鱼丸 ⋅ 2016/08/15 ⋅ 0

23种设计模式(8):观察者模式

定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。 类型:行为类模式 类图: 在软件系统中经常会有这样的需求:如果一个对象...

LCZ777 ⋅ 2014/07/06 ⋅ 0

zookeeper 观察者-学习笔记

除了leader和follow模式之外,还有第三种模式:observer模式。 observer和follower在一些方面是一样的。详细点来讲,他们都向leader提交proposal。 但与follower不同,observer不参与投票的过...

1066897515 ⋅ 2017/02/28 ⋅ 0

观察者模式学习

观察者模式,定义对象之间的一对多依赖关系,当被观察者的状态发生改变的时候,所有观察者得到通知并且自动更新。 这里有几个地方是这个模式需要了解的: 在被观察者类中添加观察者的时候,这...

szu_吴鹏 ⋅ 2014/04/15 ⋅ 0

Net设计模式实例之观察者模式(Observer Pattern)

一、观察者模式简介(Brief Introduction) 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化的时,会通知所有观察者对象,使他...

JORDANSG ⋅ 2013/07/15 ⋅ 1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

浅谈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

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部