假如Admin要观察User的工资变化,当User的工资增加或者减少时,都会引起Admin输出相应的信息。

定义观察者接口:MyObserver.java

package cn.liuning.watch;

public interface MyObserver {
void update(MyObservable o, Object arg);
}

定义被观察者父类(Admin类需要继承这个类):MyObservable.java

package cn.liuning.watch;

import java.util.Observer;
import java.util.Vector; /**
* 观察者模式,Java源码
* @author liuning
*
*/
public class MyObservable {
/**
* 标记是否被观察这改变
*/
private boolean changed = false; /**
* 保存所有的观察者
*/
private Vector<MyObserver> all; /**
* 观察者构造函数
*/
public MyObservable(){
all = new Vector<MyObserver>();
} /**
* 增加一个观察者
* @param o
*/
public synchronized void addObserver(MyObserver o){
if(o == null){
throw new NullPointerException();
}
if(!all.contains(o)){
all.addElement(o);
}
} /**
* 删除一个观察者
* @param o
*/
public synchronized void deleteObserver(Observer o) {
all.removeElement(o);
} /**
* 被观察这通知观察者做出相应的变化
*/
public void notifyObservers() {
notifyObservers(null);
} /**
* 被观察这通知观察者做出相应的变化
*/
public void notifyObservers(Object arg) { Object[] arrLocal;
synchronized (this) {
if (!changed){
return ;
}
arrLocal = all.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--){
((MyObserver)arrLocal[i]).update(this, arg);
}
} /**
* 删除所有观察者
*/
public synchronized void deleteObservers() {
all.removeAllElements();
} /**
* 设置被观察这发生变化
*/
protected synchronized void setChanged() {
changed = true;
} /**
* 清除变化
*/
protected synchronized void clearChanged() {
changed = false;
} /**
* 判断是否有变化
* @return boolean
*/
public synchronized boolean hasChanged() {
return changed;
} /**
* 计数,获取观察者个数
* @return
*/
public synchronized int countObservers() {
return all.size();
} }

定义观察者(需要实现MyObservable接口):Admin.java

package cn.liuning.watch;

public class Admin implements MyObserver{

    @Override
public void update(MyObservable o, Object arg) { User user = (User) o; System.out.println(arg+"钱改变了"); System.out.println(user.toString());
} }

定义被观察者(需要继承MyObserver):User.java

package cn.liuning.watch;

public class User extends MyObservable{
private int price = 0;
private String name = "张三"; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
} @Override
public String toString() {
return "User [price=" + price + ", name=" + name + "]";
}
public void setPrice(int price) { this.price = price; //设置工资发生变化
this.setChanged(); //通知观察者执行,内部就是调用所有观察者的update方法,通过接口实现。
this.notifyObservers(this.name);//可午餐也可有参
} }

测试Main方法:Test.java

package cn.liuning.watch;

public class Test {
public static void main(String[] args) { //被观察者初始化
User user = new User(); //增加一个观察者
user.addObserver(new Admin()); user.setName("李四");
//当价格改变时就会观察者就会执行update方法。
user.setPrice(100); }
}

Java内部实现的观察者模式小记的更多相关文章

  1. Java常见设计模式之观察者模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Mo ...

  2. JAVA基础——设计模式之观察者模式

    观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependen ...

  3. 《JAVA设计模式》之观察者模式(Observer)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Mo ...

  4. Java内部DNS查询实现和参数设置

    一.Java内部DNS查询 Java使用域名查询时,用的自己内部的域名实现机制,最后都是交给InetAddress去做DNS解析. 源码分析参考:http://blog.arganzheng.me/p ...

  5. Java设计模式之《观察者模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6513651.html 观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监 ...

  6. c#:对两个字符串大小比较(不使用c#/java内部的比较函数),按升序排序

    题目:首先需要实现一个函数:两个字符串大小比较(不得使用c#/java系统函数)的自定义函数:之后对一个字符串数据进行按升序排序(在排序过程中使用字符串大小比较时,使用自定义的字符串大小比较函数). ...

  7. Python学习---Java和Python的区别小记

    Java和Python的区别小记 注意这里使用的是 and/or/not  非java中的&&,||,!Java中的true是小写 Python中函数就是对象,函数和我们之前的[1,2 ...

  8. Java设计模式百例 - 观察者模式

    观察者(Observer)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主体对象的状态变化会通知所有观察者对象.观察者模式又叫做发布-订阅(Publish/Subscribe ...

  9. Java内部锁的可重用性(Reentrancy)

    Java提供了强制原子性的内部锁机制:synchronized块.但是内部锁是可重入的,当线程试图获得它自己占有的锁时,请求会成功. 简单的说,就是在一个synchronized方法内部调用本类的其他 ...

随机推荐

  1. java实验报告三 敏捷开发与XP

    20145306 java 实验三 实验报告 实验内容 1.git下载结对同学的代码 2.修改结对同学的代码 3.实现代码重构 实验步骤 新建存储空间 git下载代码 将修改后的代码上传 上传结果 重 ...

  2. Loadrunner:集合点(Rendezvous)

    集合点:等到特定的用户数后再一起执行某个操作,比如一起登录.一起发信,一般情况下使用不到集合点,不过,订票系统或者促销类需要用到,比如说某个促销品的促销时间在8点到8点30,这样的话,就可能出现在8点 ...

  3. [原]hdu2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (这个只是题目名字) (多重背包)

    本文出自:http://blog.csdn.net/svitter 原题:http://acm.hdu.edu.cn/showproblem.php?pid=2191 题意:多重背包问题.转换成为01 ...

  4. JavaScript学习小结(一)——JavaScript入门基础

    一.JavaScript语言特点 1.1.JavaScript是基于对象和事件驱动的(动态的) 它可以直接对用户或客户输入做出响应,无须经过Web服务程序.它对用户的响应,是采用以事件驱动的方式进行的 ...

  5. 一个简单且丑陋的js切换背景图片基础示例

    不多说,直接上代码,非常基础的一个原生js切换元素背景图片范例 <html> <head> <meta http-equiv="Content-Type&quo ...

  6. c# dataset 索引0没有值

    datatable绑定到dataGrieView,在刷新datatable的数据时,常会bug:索引0没有值或索引(int)x没有值 昨天弄了一个下午,发现bug原因: dataGridView中有数 ...

  7. Android消息推送完美方案[转]

    转自 Android消息推送完美方案 推送功能在手机应用开发中越来越重要,已经成为手机开发的必须.在Android应用开发中,由于众所周知的原因,Android消息推送我们不得不大费周折.本文就是用来 ...

  8. Android———从GitHub上下载源码的方法【Written By KillerLegend】

    首先声明,本文说的是从GitHub上下载源码而非上传源码! 1:下载tortoisegit,下载地址为: https://code.google.com/p/tortoisegit/wiki/Down ...

  9. Python学习教程(learning Python)--2.3.2 Python函数实参详解

    本节主要讨论函数调用时参数的实参问题. 1. 实参赋值顺序和型参定义顺序一一对应 Python在调用哪个子函数时,如果型参为多个,一般实参的排布顺序和型参顺序保持一致,即一一对应.我们以下面的代码为例 ...

  10. 《Prism 5.0源码走读》Bootstrapper

    Prism框架需要在应用程序启动的时候进行一些初始化的工作,Bootstrapper就是来做这些的,是其切入点. Bootstrapper主要要做的事有:创建和配置module catalog,创建D ...