• 观察者模式介绍

  观察者模式是一种非常有用的设计模式,在软件系统中,当一个对象的行为依赖于另一个对象的状态时,观察者模式就非常有用。如果不适用观察者模式,而实现类似的功能,可能就需要另外启动一个线程不停地监听另一个对象的状态,这样会得不偿失。如果在一个复杂的系统中,可能就需要开启很多的线程来监听对象状态的变化,这样会使系统的性能产生额外的负担。而观察者模式就可以在单线程下使某一对象及时得知所依赖对象状态的变化而做出行为。

  观察者模式的经典结构:

  

  其中ISubject是观察对象(被观察者对象),它维持着一个观察者对象列表,可以增加或删除观察者。IObserver是观察者,它依赖于ISubject对象状态的变化而做出行为。当ISubject对象的状态发生变化时,它可以通过inform()方法通知观察者。

  观察者模式的主要角色功能如下图:

  

  • 观察者实例

  现在简单实现一个观察者的小例子。

  主题接口:

 public interface ISubject {
void attach(IObserver observer);
void detach(IObserver observer);
void inform();
}

  观察者接口:

 public interface IObserver {
void update(Event event);
}

  事件(对应现实中的点击等事件也可以理解为上文中说到的状态变化):

 public class Event {

 }

  具体的主题实现:

 public class ConcreteSubject implements ISubject {
Vector<IObserver> obversers = new Vector<IObserver>();//观察者队列
@Override
public void attach(IObserver observer) {
obversers.add(observer);
} @Override
public void detach(IObserver observer) {
obversers.remove(observer);
} @Override
public void inform() {
Event event = new Event();
for(IObserver obverser:obversers){
obverser.update(event);
}
} }

  具体的观察者:

 public class ConcreteObserver implements IObserver {

     @Override
public void update(Event event) {
System.out.println("ConcreteObserver.update()");
} }

  测试代码:

public class Test {
public static void main(String[] args) {
IObserver observer1 = new ConcreteObserver();
IObserver observer2 = new ConcreteObserver();
ISubject subject = new ConcreteSubject();
subject.attach(observer1);
subject.attach(observer2);
subject.inform();
}
}

  可以看出,通过被观察者状态变化而调用某一方法使观察者收到通知而做出反应,通过委托降低了代码的耦合度。

  观察者模式十分常用,以致于JDK内部就为开发人员准备了一套观察者模式的实现。在java.util包中,就包括了Obserable类和Observer接口。在Observable中就实现了观察对象的主要功能,如:添加观察者、删除观察者和通知观察者等。Observer是观察者接口,它的update方法会在Obserable类的notifyObservers()中被回调以获得最新的状态变化。

  以现在比较火热的购房作为观察者模式的一个例子:现在很多购房者关注房价的变化,每当房价发生变动的时候,购房者就会收到通知。这样购房者就是观察者,他们关注着房子的价格。

  观察对象房子代码:

 public class House extends Observable{
private float price; public House(float price) {
super();
this.price = price;
} public float getPrice() {
return price;
} public void setPrice(float price) {
super.setChanged();//设置变化点
super.notifyObservers(price);//价格变动
this.price = price;
} @Override
public String toString() {
// TODO Auto-generated method stub
return "房子的价格为:"+this.price;
}
}

  观察者购房者代码:

 public class CustomerObserver implements Observer{

     private String name;

     public CustomerObserver(String name) {
super();
this.name = name;
} @Override
public void update(Observable o, Object arg) {
if (arg instanceof Float) {
System.out.println(this.name+"观察到房子价格变动为:"+arg);
}
}
}

  测试代码:

 public class Test1 {
public static void main(String[] args) {
House h = new House(1000000) ;
CustomerObserver hpo1 = new CustomerObserver("购房者A") ;
CustomerObserver hpo2 = new CustomerObserver("购房者B") ;
CustomerObserver hpo3 = new CustomerObserver("购房者C") ;
h.addObserver(hpo1) ;
h.addObserver(hpo2) ;
h.addObserver(hpo3) ;
System.out.println(h) ; // 输出房子价格
h.setPrice(666666) ; // 修改房子价格
System.out.println(h) ; // 输出房子价格
}
}

  输出结果为:

 房子价格为:1000000.0
购房者C观察到价格更改为:666666.0
购房者B观察到价格更改为:666666.0
购房者A观察到价格更改为:666666.0
房子价格为:666666.0

  Observer源码:

 public class Observable {
private boolean changed = false;//判断观察对象是否发生变化
private Vector obs;//观察者队列
public Observable() {
obs = new Vector();
} public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
} public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
} public void notifyObservers() {
notifyObservers(null);
} //通知观察者
public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
} for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
} public synchronized void deleteObservers() {
obs.removeAllElements();
} protected synchronized void setChanged() {
changed = true;
} protected synchronized void clearChanged() {
changed = false;
} public synchronized boolean hasChanged() {
return changed;
} public synchronized int countObservers() {
return obs.size();
}
}

  可以发现JDK中实现的观察者模式,用法简单功能强大,和我们上面写的观察者模式实现原理是一样的。观察者模式可以用于事件监听、通知发布等场合,可以确保观察者在不适用轮询监控的情况下,可以及时得到相关消息和事件。

java设计优化--观察者模式的更多相关文章

  1. java设计优化--代理模式

    代理模式使用代理对象完成用户的请求,屏蔽用户对真实对象的访问. 代理模式的用途很多,比如因为安全原因,需要屏蔽客户端直接访问真实对象:或者在远程调用中,需要使用代理对象处理远程方法中的技术细节:或者为 ...

  2. java设计优化--单例模式

    单例模式是一种对象创建模式,确保系统中一个类只有一个实例. 在java语言中,这样做有两大好处: 1.对于频繁使用的对象,可以省略创建对象所话费的时间: 2.由于new操作的次数减少,对于系统内存的使 ...

  3. java设计优化--装饰者模式

    装饰者模式拥有一个设计非常巧妙的结构,它可以动态的添加功能.在基本的设计原则中,有一条重要的设计准则就是合成/聚合复用原则.根据该原则的思想,代码复用应该尽可能使用委托,而不是使用继承.因为继承是一种 ...

  4. java设计优化-享元模式

    享元模式是设计模式中少数几个以调高系统性能为目的的设计模式.它的核心思想是:如果在一个系统中存在多个相同的对象,那么只需共享一份对象的拷贝,而不必为每一次使用都创建新的对象.在享元模式中,由于需要构建 ...

  5. 《Java程序性能优化》学习笔记 设计优化

    豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞 ...

  6. 《Java程序性能优化》之设计优化

    豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞 ...

  7. Java 程序优化 (读书笔记)

    --From : JAVA程序性能优化 (葛一鸣,清华大学出版社,2012/10第一版) 1. java性能调优概述 1.1 性能概述 程序性能: 执行速度,内存分配,启动时间, 负载承受能力. 性能 ...

  8. 从设计模式的角度看Java程序优化

    一.前言 Java程序优化有很多种渠道,比如jvm优化.数据库优化等等,但都是亡羊补牢的措施,如果能在设计程序架构时利用设计模式就把程序的短板解决,就能使程序更加健壮切容易维护迭代 二.常用的设计模式 ...

  9. JAVA性能优化的五种方式

    一,JAVA性能优化之设计优化 设计优化处于性能优化手段的上层.它往往须要在软件开发之前进行.在软件开发之前,系统架构师应该就评估系统可能存在的各种潜在问题和技术难点,并给出合理的设计方案,因为软件设 ...

随机推荐

  1. Centos7 搭建hadoop2.6 HA

    用户配置: User :root Password:toor 2.创建新用户 student Pwd: student 3.安装virtualbox的增强工具软件 4.系统默认安装的是openjdk ...

  2. [译]OpenStack Object Storage Monitoring

    注:翻译的不完整,主要是有些地方翻译后反而妨碍理解,有些不知道怎么翻,anyway,需要时拿来用用也是可行的,顺便共享啦.欢迎提意见. 一个OpenStack Object Storage(OSOS) ...

  3. vmware12安装vmtools

    一. 1. 机器要开启支持BIOS的选项. 二. 1. 点击vmware 应用 vmware install 2. 虚拟机: tar  xvf vmtools-distb.tgr.gz 3. 虚拟机: ...

  4. 对比git rm和rm的使用区别

    在这里说一下git rm和rm的区别,虽然觉得这个问题有点肤浅,但对于刚接触git不久的朋友来说还是有必要的. 用 git rm 来删除文件,同时还会将这个删除操作记录下来:用 rm 来删除文件,仅仅 ...

  5. Javascript 中的 in, hasOwnProperty, delete, for/in

    in 运算符 判断对象是否拥有某一属性只要对象拥有该属性,就会返回true,否则false var point = { x:1, y:1 };alert( 'x' in point );  //tru ...

  6. 11Mybatis_mybatis开发Dao的方法

    在介绍开发Dao的方法之前先介绍下SqlSession. 1.先介绍一下SqlSessionFactoryBuilder:通过SqlSessionFactoryBuilder创建会话工厂SqlSess ...

  7. 【转】【UML】使用Visual Studio 2010 Team System中的架构师工具(设计与建模)

    Lab 1: 应用程序建模 实验目标 这个实验的目的是展示如何在Visual Studio 2010旗舰版中进行应用程序建模.团队中的架构师会通过建模确定应用程序是否满足客户的需求. 你可以创建不同级 ...

  8. Kakfa分布式集群搭建

    本位以最新版本kafka_2.11-0.10.1.0版本讲述分布式kafka集群环境的搭建过程.服务器列表: 172.31.10.1 172.31.10.2 172.31.10.3 1.下载kafka ...

  9. Linux 图形化操作

    //Linux图形化操作 #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...

  10. JS案例之4——Ajax多图上传

    近期项目中有好几次用到多图上传,第一次在项目中真正用到Ajax技术,稍微整理了下,贴个案例出来. 我们传统的做法是当用户提交一个表单时,就向web服务器端发送一个请求.服务器接受并处理传来的表单信息, ...