`
zzq19860626
  • 浏览: 261010 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
B20df9e2-fb3d-3644-9f72-c1619842f682
设计模式学习笔记
浏览量:177982
87eaf24f-812a-3463-8e65-e3197d2ad8c2
java虚拟机
浏览量:26189
社区版块
存档分类
最新评论

JAVA设计模式学习19——观察者模式

阅读更多
观察者(Observer)模式:是对象的行为模式,又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听(Source/Listener)模式或者从属(Dependents)模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式类的结构:
观察者模式角色如下:
抽象主题(Subject)角色:抽象主题角色提供维护一个观察者对象聚集的操作方法,对聚集的增加、删除等。
具体主题(ConcreteSubject)角色:将有关状态存入具体的观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色负责实现抽象主题中聚集的管理方法。
抽象观察者(Observer)角色:为具体观察者提供一个更新接口。
具体观察者(ConcreteObserver)角色:存储与主题相关的自洽状态,实现抽象观察者提供的更新接口。
 
仔细观察上面的类图,发现具体主题角色和抽象观察者之间的连线,是因为具体主题角色维护了一个观察者引用的聚集,如果有多个具体主题角色,意味着每个具体角色都要维护一个观察者的聚集,那么能不能将聚集提升到抽象主题里面呢?这个就需要考虑场景,如果多个主题实现在管理上都有很大差异,那么就不能提升到抽象角色中,但是绝大多数情况下,这些聚集管理方法本身就是所有具体主题所共有的,所以大多数情况下都是可以将聚集和聚集的管理都移入到抽象主题中的,因为notifyObserver()方法是依赖于聚集的,所以将notifyObserver()也移入抽象主题中,这样就形成了如下的另一种观察者模式结构:

 我们这里简单用代码描述如下:
package observer.desc;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午8:05:08
 *描述:抽象观察者
 */
public interface Observer {
	
	public void update();
	
}
 
package observer.desc;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午8:05:34
 *描述:具体观察者
 */
public class ConcreteObserver implements Observer{

	@Override
	public void update() {
		// 写业务逻辑
	}

}
 
package observer.desc;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午8:05:55
 *描述:抽象主题
 */
public interface Subject {

	public void attach(Observer observer);

	public void detach(Observer observer);

	void notifyObservers();
}
 
package observer.desc;

import java.util.Enumeration;
import java.util.Vector;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午8:09:21
 *描述:具体主题类
 */
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 notifyObservers() {
		Enumeration<Observer>enumeration = observers();
		while (enumeration.hasMoreElements()) {
			((Observer) enumeration.nextElement()).update();
		}
	}

	@SuppressWarnings("unchecked")
	public Enumeration<Observer> observers() {
		return ((Vector<Observer>) observersVector.clone()).elements();
	}

} 
上面代码描述第一种形式,第二种读者可以自己实现,这里不再赘述。
接下来我们看java语言是如何支持观察者模式的,java提供一个被观察者类java.util.Observable和一个观察者接口java.util.Observer。

jdk1.6中API文档如下描述:

public interface Observer

一个可在观察者要得到 observable 对象更改通知时可实现 Observer 接口的类。

从以下版本开始:

JDK1.0

另请参见:

Observable

 

public class Observableextends Object

此类表示模型视图范例中的 observable 对象,或者说“数据”。可将其子类化,表示应用程序想要观察的对象。

一个 observable 对象可以有一个或多个观察者。观察者可以是实现了 Observer 接口的任意对象。一个 observable 实例改变后,调用 Observable 的 notifyObservers 方法的应用程序会通过调用观察者的 update 方法来通知观察者该实例发生了改变。

 

未指定发送通知的顺序。Observable 类中所提供的默认实现将按照其注册的重要性顺序来通知 Observers,但是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知,或者也可能保证其子类遵从其所选择的顺序。

 

注意,此通知机制与线程无关,并且与 Object 类的 wait 和 notify 机制完全独立。 新创建一个 observable 对象时,其观察者集是空的。当且仅当 equals 方法为两个观察者返回 true 时,才认为它们是相同的。

 

从以下版本开始:

JDK1.0

另请参见: 

notifyObservers(), notifyObservers(java.lang.Object), Observer, Observer.update(java.util.Observable, java.lang.Object)

 

举个例子,如果你看过TVB的警匪片,你就知道卧底的工作方式。一般一个警察可能有几个卧底,潜入敌人内部,打探消息,卧底完全靠他的领导的指示干活,领导说几点行动,他必须按照这个时间去执行,如果行动时间改变,他也要立马改变自己配合行动的时间。领导派两个卧底去打入敌人内部,那么领导相当于抽象主题,而督察警官张三这个人派了两个卧底李四和万王五,张三就相当于具体主题,卧底相当于抽象观察者,这两名卧底是李四和王五就是具体观察者,派的这个动作相当于观察者在主题的登记。那么这个类图如下:
利用javaAPI来实现,代码描述如下: 
package observer;

import java.util.List;
import java.util.Observable;
import java.util.Observer;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午9:32:40
 *描述:警察张三
 */
public class Police extends Observable {

	private String time ;
	public Police(List<Observer> list) {
		super();
		for (Observer o:list) {
			addObserver(o);
		}
	}
    public void change(String time){
    	this.time = time;
    	setChanged();
    	notifyObservers(this.time);
    }
}
 
package observer;

import java.util.Observable;
import java.util.Observer;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午9:32:59
 *描述:卧底A
 */
public class UndercoverA implements Observer {

	private String time;
	@Override
	public void update(Observable o, Object arg) {
		time = (String) arg;
		System.out.println("卧底A接到消息,行动时间为:"+time);
	}


}
 
package observer;

import java.util.Observable;
import java.util.Observer;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午9:33:14
 *描述:卧底B
 */
public class UndercoverB implements Observer {
	private String time;
	@Override
	public void update(Observable o, Object arg) {
		time = (String) arg;
		System.out.println("卧底B接到消息,行动时间为:"+time);
	}



}
 
package observer;

import java.util.ArrayList;
import java.util.List;
import java.util.Observer;
/**
 * 
 *作者:alaric
 *时间:2013-8-13下午9:32:26
 *描述:测试
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		UndercoverA o1 = new UndercoverA();
		UndercoverB o2 = new UndercoverB();
		List<Observer> list = new ArrayList<>();
		list.add(o1);
		list.add(o2);
		Police subject = new Police(list);
		subject.change("02:25");
		System.out.println("===========由于消息败露,行动时间提前=========");
		subject.change("01:05");
		
	}

}

 测试运行结果:

卧底B接到消息,行动时间为:02:25

卧底A接到消息,行动时间为:02:25

===========由于消息败露,行动时间提前=========

卧底B接到消息,行动时间为:01:05

卧底A接到消息,行动时间为:01:05

观察者模式的优点是只要订阅/登记了之后,当被观察者改变时,观察者能自动更新。跟JMS一样,消息发布者发出消息时,只要注册过的都会收到消息。
  

设计模式系列目录:

  • 大小: 16.1 KB
  • 大小: 17.4 KB
  • 大小: 20 KB
6
3
分享到:
评论
6 楼 hcwlqh 2013-10-16  
5 楼 czy895 2013-09-14  

第一次这么形象的看观察者模式,写的很好。
4 楼 cooper100 2013-08-15  
3 楼 kiven 2013-08-14  
很形象,听明白。
2 楼 zef1100 2013-08-14  
1 楼 nirenli 2013-08-13  

相关推荐

    java设计模式

    22.4.1 Java世界中的观察者模式 22.4.2 项目中真实观察者模式 22.4.3 订阅发布模型 22.5 最佳实践 第23章 门面模式 23.1 我要投递信件 23.2 门面模式的定义 23.3 门面模式的应用 23.3.1 门面模式的优点 23.3.2 门面...

    深入浅出设计模式(中文版电子版)

    5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...

    深入浅出设计模式(中文版)

    5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷6

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷8

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷3

    pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 pattern/src/behavior/chainofresponsibility//13.5责任链模式 pattern/src/behavior/command //13.6命令模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷1

    pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 pattern/src/behavior/chainofresponsibility//13.5责任链模式 pattern/src/behavior/command //13.6命令模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷9

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷10

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷5

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷7

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷2

    pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 pattern/src/behavior/chainofresponsibility//13.5责任链模式 pattern/src/behavior/command //13.6命令模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷4

    pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 pattern/src/behavior/chainofresponsibility//13.5责任链模式 pattern/src/behavior/command //13.6命令模式 ...

    Java开发详解.zip

    031114_【第11章:Java常用类库】_观察者设计模式笔记.pdf 031115_【第11章:Java常用类库】_正则表达式笔记.pdf 031116_【第11章:Java常用类库】_定时调度笔记.pdf 031201_【第12章:JAVA IO】_File类笔记.pdf ...

    asp.net知识库

    动态调用对象的属性和方法——性能和灵活性兼备的方法 消除由try/catch语句带来的warning 微软的应试题完整版(附答案) 一个时间转换的问题,顺便谈谈搜索技巧 .net中的正则表达式使用高级技巧 (一) C#静态成员和...

    Python编程入门经典

    4.5 观察多个比较运算的结果 54 4.6 循环 57 4.6.1 重复执行操作 57 4.6.2 终止循环 59 4.7 处理错误 62 4.8 本章小结 64 4.9 习题 65 第5章 函数 67 5.1 将程序放在单独的文件中 67 5.2 函数:在一个名称下聚集 ...

    webx3框架指南PDF教程附学习Demo

    Webx也是如此 —— 它在某些方面有一些独到的设计,超越了同类框架。Webx有哪些优势呢? Webx的优势 成熟可靠性 这个优势主要是针对阿里巴巴及属下网站而言。因为Webx在阿里巴巴和淘宝用了很多年。对于这种超大...

Global site tag (gtag.js) - Google Analytics