Java内部实现的观察者模式小记
假如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内部实现的观察者模式小记的更多相关文章
- Java常见设计模式之观察者模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Mo ...
- JAVA基础——设计模式之观察者模式
观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependen ...
- 《JAVA设计模式》之观察者模式(Observer)
在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Mo ...
- Java内部DNS查询实现和参数设置
一.Java内部DNS查询 Java使用域名查询时,用的自己内部的域名实现机制,最后都是交给InetAddress去做DNS解析. 源码分析参考:http://blog.arganzheng.me/p ...
- Java设计模式之《观察者模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6513651.html 观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监 ...
- c#:对两个字符串大小比较(不使用c#/java内部的比较函数),按升序排序
题目:首先需要实现一个函数:两个字符串大小比较(不得使用c#/java系统函数)的自定义函数:之后对一个字符串数据进行按升序排序(在排序过程中使用字符串大小比较时,使用自定义的字符串大小比较函数). ...
- Python学习---Java和Python的区别小记
Java和Python的区别小记 注意这里使用的是 and/or/not 非java中的&&,||,!Java中的true是小写 Python中函数就是对象,函数和我们之前的[1,2 ...
- Java设计模式百例 - 观察者模式
观察者(Observer)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主体对象的状态变化会通知所有观察者对象.观察者模式又叫做发布-订阅(Publish/Subscribe ...
- Java内部锁的可重用性(Reentrancy)
Java提供了强制原子性的内部锁机制:synchronized块.但是内部锁是可重入的,当线程试图获得它自己占有的锁时,请求会成功. 简单的说,就是在一个synchronized方法内部调用本类的其他 ...
随机推荐
- (图 BFS)走迷宫
题目: 给一个迷宫,求出从起点到终点的路径.迷宫 src.txt 文件内容如下,第一行是迷宫的行列数,后面行是迷宫,1表示可行走,0表示不可以通过,起点是最左上角,终点是最右下角: 解析: 其实就是图 ...
- HTML5应用之时钟
利用HTML5的Canvas API可以完成我们以前意想不到的动画效果,以前我们想在网页上放置一个时钟,需要先用flash工具制作一个钟表,并写上复杂的JavaScript代码,然后载入到页面中.而H ...
- 复杂的databinding接受Ilist作为数据源
Combobox控件绑定数据源时,List<T>可以作为数据源,但是List<String,Object> 不存在,我们有时候需要用Dictionary<String,o ...
- Linux文件系统的主要目录结构说明及分区方案
Linux操作系统有一些固定的目录.各种Linux发行版的目录结构虽然不会一模一样,但是不会有很大差异.知道了这些目录的作用,不仅对你进行磁盘分区规划很有帮助,而且会让你以后的日常维护工作变得轻松.只 ...
- Jquery 实现json复杂查询等操作(jsonDB)
一.jsonDB 下载地址:https://github.com/ThinkerCodeChina/jsonDB jsonDB是js的一个类库,实现使用SQL语句对json数据增删改查.jsonDB的 ...
- U盘启动
2014.4.3修改 其实用U盘制作系统也可以下载一个软碟通UltraISO,就可以很方便的制作. ----以前的版本 用U盘装系统,很方便快捷,下面这个网站介绍的比较详细,于是自己整理了一下,作为收 ...
- PHP取当前页面完整URL地址
#测试网址: http://localhost/blog/testurl.php?id=5 //获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br> ...
- python 循环、循环设计、循环对象
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 1.循环 循环用于重复执行一些程序块.从上一讲的选择结构,我们已经看到了如何用缩进 ...
- linux 使用 pyodbc 访问 ms sqlserver 数据库
一.安装linux下Sqlserver的驱动程序: 我们先来安装SqlServer的驱动程序,再安装ODBC相关的,目的是想尽快可以进行测试,因为在安装完Freetds之后,我们马上就可以在linux ...
- Activity(一)
一个应用程序中至少包含一个Activity,Activity启动流程:当启动一个应用程序时,android操作系统会访问该应用程序的AndroidManifest.xml文件(该文件中说明了应用程序使 ...