观察者模式定义了对象间的一对多依赖关系,让一个或多个观察者对象观察一个主题对象。当主题对象的状态发生变化时,系统恩那个通知所有的依赖于此对象观察者对象,从而使得观察者对象能够自动更新。

  在观察者模式中,被观察的对象尝尝被称为目标或主题(Subject),依赖的对象被称为观察者(Observer)。

  Interface:Observer

package edu.pri.lime._9_3_9.bean;

//观察者接口,程序中所有观察者都应该实现该接口
public interface Observer { // Observable:代表被观察对象,即目标或主题
// Observable:是一个抽象基类,程序中被观察者应该继承该抽象基类。
// arg:
void update(Observable o,Object arg); }

  Class:Observable

package edu.pri.lime._9_3_9.bean;

import java.util.ArrayList;
import java.util.List;
/*
* 该抽象类是所有被观察者(主题)的基类,
* 它提供了registObserver()方法用于注册一个新的观察者;
* 并提供了一个removeObserver()方法用于删除一个已注册的观察者;
* 当具体被观察对象(主题)的状态发生改变时,具体被观察对象(主题)会调用notifyObservers()方法来通知所有观察者。
*/
public abstract class Observable { // 用一个List来保存该对象上所有绑定的事件监听器
List<Observer> observers = new ArrayList<Observer>();
// 用于从该主题上注册观察者
public void registObserver(Observer o){
observers.add(o);
}
// 用于从该主题上注册观察者
public void removeObserver(Observer o){
observers.remove(o);
}
// 通知该主题上注册的所有观察者
public void notifyObservers(Object value){
// 遍历注册到该主题上的所有被观察者
for(Observer o : observers){
// 显式调用每个观察者的update()方法
o.update(this, value);
}
}
}

  Class:Product

package edu.pri.lime._9_3_9.bean;

public class Product extends Observable {

    private String name;
private double price;
public Product() {
super();
// TODO Auto-generated constructor stub
}
public Product(String name, double price) {
super();
this.name = name;
this.price = price;
}
// 当程序调用name的setter方法来修改Product的name成员变量时,
// 程序自然触发该对象上注册的所有观察者
public void setName(String name) {
this.name = name;
notifyObservers(name);
}
// 当程序调用price的setter方法来修改Product的price成员变量时,
// 程序自然触发该对象上注册的所有观察者
public void setPrice(double price) {
this.price = price;
notifyObservers(price);
}
public String getName() {
return name;
}
public double getPrice() {
return price;
} }

  Class:NameObserver

package edu.pri.lime._9_3_9.bean;

import javax.swing.JFrame;
import javax.swing.JLabel; public class NameObserver implements Observer { // 实现观察者必须实现的update方法
public void update(Observable o, Object arg) {
if(arg instanceof String){
String name = (String) arg;
JFrame f = new JFrame("观察者");
JLabel l = new JLabel("名称改变为:" + name);
f.add(l);
f.pack();
f.setVisible(true);
System.out.println("名称观察者:" + o + "物品名称已改变为:" + name);
}
}
}

  Class:PriceObserver

package edu.pri.lime._9_3_9.bean;

public class PriceObserver implements Observer {

//    实现观察者必须实现的update()方法
public void update(Observable o, Object arg) {
if(arg instanceof Double){
System.out.println("价格观察者:" + o + "物品价格已改变为:" + arg);
}
} }

  Class:Test

package edu.pri.lime._9_3_9.main;

import edu.pri.lime._9_3_9.bean.NameObserver;
import edu.pri.lime._9_3_9.bean.PriceObserver;
import edu.pri.lime._9_3_9.bean.Product; public class Test { public static void main(String[] args) throws InterruptedException{
// 创建一个主题对象
Product pro = new Product("桌子",300);
// 创建两个观察者对象
NameObserver nameObs = new NameObserver();
PriceObserver priObs = new PriceObserver();
// 向主题对象上注册两个观察者对象
pro.registObserver(nameObs);
pro.registObserver(priObs);
// 程序调用setter方法来改变Product的name和price成员变量
pro.setName("高级书桌");
Thread.sleep(3000);
pro.setPrice(321d);
}
}

  观察者模式通常包含如下4个角色:

    ⊙ 被观察者(主题)的抽象基类:它通常会持有多个观察者对象的引用。Java提供了java.util.Observable基类来代表被观察者(主题)的抽象基类,所以实际开发中无须自己开发这个角色。

    ⊙ 观察者接口:该接口是所有观察者对象应该实现的接口,通常它只包含一个抽象方法update()。Java同样提供了java.util.Observer接口来代表观察者接口,实际开发中也无须开发该角色。

    ⊙ 被观察者实现类(主题):该类继承Observable基类。

    ⊙ 观察者实现类:实现Observer接口,实现update()抽象方法。

  实际上,完全额可以把观察者借口理解成时间监听接口,而被观察者对象(主题)也可当成事件源来处理。Java事件机制的底层实现,本身就是通过观察者模式来实现的。

  除此之外,观察者模式在Java EE应用中也有广泛的应用,主题/订阅模式下的JMS(Java Message Service,Java消息服务)本身就是观察者模式的应用。

GoF--观察者模式的更多相关文章

  1. RxJava开发精要2-为什么是Observables?

    原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...

  2. RxJava(一):响应式编程与Rx

    一,响应式编程 响应式编程是一种关注于数据流(data streams)和变化传递(propagation of change)的异步编程方式. 1.1 异步编程 传统的编程方式是顺序执行的,必须在完 ...

  3. 每天翻译一点点: WPF Application Framework (WAF)

    ps:http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&referringTitle=Document ...

  4. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  5. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  6. GOF业务场景的设计模式-----观察者模式

    定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新. 在软件系统中经常会有这样的需求:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出 ...

  7. 设计模式-GoF

    资源: 下载GOF的书籍: http://download.csdn.net/download/quanbove/6534569 这里总结了模式,但讲的并不准确: http://www.runoob. ...

  8. [python实现设计模式]-4.观察者模式-吃食啦!

    观察者模式是一个非常重要的设计模式. 我们先从一个故事引入. 工作日的每天5点左右,大燕同学都会给大家订饭. 然后7点左右,饭来了. 于是燕哥大吼一声,“饭来啦!”,5点钟定过饭的同学就会纷纷涌入餐厅 ...

  9. 为什么GOF的23种设计模式里面没有MVC?

    GoF (Gang of Four,四人组, <Design Patterns: Elements of Reusable Object-Oriented Software>/<设计 ...

  10. Android使用的设计模式1——观察者模式

    设计模式,对程序员来说是一个坎,想在程序员这条路走得更远,设计模式是你的必修课.从大学时代接触GoF到工作几年后重新看设计模式,每次感觉都不一样.这次想借着分析Android Framework源码的 ...

随机推荐

  1. select in 在postgresql的效率问题

    在知乎上看到这样一个问题: MySQL 查询 select * from table where id in (几百或几千个 id) 如何提高效率?修改 电商网站,一个商品属性表,几十万条记录,80M ...

  2. iis7 64位 操作excel的一系列问题(未完待续)

    查了半天发现是IIS跑在64位环境下引起的.而64位下,是木有Access数据库的驱动的(包括Excel也不行). 解决办法是:在目标网站的应用程序池中选择高级设置,然后将启用32位应用程序设置为tr ...

  3. ios webView 放大网页解决/input 获得焦点focus 网页放大 解决

    新手遇到的问题: 终于找到原因,各种HTML viewport 都试过 setScalePageToFit 也试过,webViewDidFinishLoad加JS代码,动态算webView.scrol ...

  4. barManager 挤压后“ 自动换行”和“自动隐藏”的实现方法

  5. 2013ACM/ICPC亚洲区南京站现场赛-HDU4809(树形DP)

    为了这个题解第一次写东西..(我只是来膜拜爱看touhou的出题人的).. 首先以为对称性质..我们求出露琪诺的魔法值的期望就可以了..之后乘以3就是答案..(话说她那么笨..能算出来么..⑨⑨⑨⑨⑨ ...

  6. apache2.4配置Django1.7运行环境

    系统环境Centos 6.5 这篇文章不适用6以下的系统,因为会碰到这个错误 [Mon Sep 22 18:13:02 2014] [error] [client 10.209.75.90] Trun ...

  7. Write Your software base on plugin(C/C++ ABI)

    一个软件,如果把所有的功能写进C++源码,维护,扩展,编译都特别麻烦. 共享库后缀名.Linux -> .so  Windows -> .dll 关于动态符号显示问题,具体可以看系统的AP ...

  8. 在SpringMVC框架下实现文件的 上传和 下载

    在eclipse中的javaEE环境下:导入必要的架包 web.xml的配置文件: <?xml version="1.0" encoding="UTF-8" ...

  9. Nudnik Photographer -Ural1260动态规划

    Time limit: 1.0 second Memory limit: 64 MB If two people were born one after another with one second ...

  10. [DataBase] MongoDB (8) 副本集

    MongoDB  创建副本集 MongoDB复制是将数据同步在多个服务器的过程. 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. 复制还允许您从 ...