设计模式初探-观察者模式(一)

2014-11-24 02:40:50 · 作者: · 浏览: 2

观察者模式(OBSERVER),又称发布-订阅(Publish-Subscribe),依赖(Dependents),通过定义对象间的一对多的依赖关系,达到当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新,属于对象行为型模式。观察者模式在软件设计中很常用,比如经典的MVC模式,Model为目标类,View为观察者,Controller为更新管理器。首先更新管理器即控制器先将视图和模型建立关联关系,然后当模型数据改变时,这些改变会自动反映在视图上,从而达到了业务和显示分离的效果。Java默认支持观察者模式,AWT1.1之后版本,Servlet,SAX2的事件处理模型均为基于观察者模式的委托事件模型(Delegation Event Model或DEM)。在DEM模型里面,主题(Subject)角色负责发布(publish)事件,而观察者角色向特定的主题订阅(subscribe)它所感兴趣的事件。当一个具体主题产生一个事件时,它就会通知所有感兴趣的订阅者。观察者模式提供了一种将发布者与订阅者松散地耦合在一起的联系形式,以及一种能够动态地登记、取消向一个发布者的订阅请求的办法。

一、使用场景

1、当一个抽象模型有两个方面,其中一个方面依赖于另一方面,将这两者封装在独立的对象中以使它们能够独立地改变和复用。

2、当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象及这些对象是谁。

3、建立链式触发机制,A影响B,B影响C,C影响D等等。

二、UML图

观察者模式uml

三、Java实现

package study.patterns.observer;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 观察者模式,又称好莱坞模式
 * Don't call me,I will call you
 * @author qbg
 */
public class ObserverPattern {
	public static void main(String[] args) {
		ClockTimerSubject timer = new ClockTimerSubject();//目标
		DigitalClock digital = new DigitalClock(timer);//观察者
		BigBenClock bigben = new BigBenClock(timer);//观察者
		TimerTask task = new TimerTask(timer);//定时任务
		task.start();//启动定时任务
	}
}
/**
 * 抽象目标类 
 */
abstract class Subject{
	protected List
  
    observers = new ArrayList
   
    (); /** * 注册观察者 */ public void attach(Observer obs){ observers.add(obs); } /** * 删除观察者 */ public void detach(Observer obs){ observers.remove(obs); } /** * 通知观察者的抽象方法 */ public abstract void notifyObs(); } /** * 具体目标类,每秒更新下自己的内部时间状态 */ class ClockTimerSubject extends Subject{ private String time; /** * 具体通知方式,通知所有观察者 */ @Override public void notifyObs() { for(Observer obs : this.observers){ obs.update(this); } } /** * 更新time,并将改变通知给观察者 */ public void tick(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); time = sdf.format(new Date()); notifyObs(); } public String getTime() { return time; } public void setTime(String time) { this.time = time; } } /** * 观察者抽象接口,只有一个update方法 */ interface Observer{ public void update(ClockTimerSubject subject); } /** * 钟表绘制接口 */ interface Widget{ public void draw(); } /** * 数字钟表,具体观察者 */ class DigitalClock implements Widget,Observer{ private ClockTimerSubject subject; /** * 初始化目标,并将自己注册到该目标的观察者列表中 */ public DigitalClock(ClockTimerSubject subject){ this.subject = subject; this.subject.attach(this); } /** * 先检查发出通知的目标是否为自己注册过的,是则响应 */ @Override public void update(ClockTimerSubject subject) { if(this.subject == subject){ draw(); } } @Override public void draw() { System.out.println("电子闹钟为您报时:"+subject.getTime()); } } /** * 大笨钟,具体观察者 */ class BigBenClock implements Widget,Observer{ private ClockTimerSubject subject; /** * 初始化目标,并将自己注册到该目标的观察者列表中 */ public BigBenClock(ClockTimerSubject subject){ this.subject = subject; this.subject.attach(this); } /** * 先检查发出通知的目标是否为自己注册过的,是则响应 */ @Override public void update(ClockTimerSubject subject) { if(this.subject == subject){ draw(); } } @Override public void draw() { System.out.println("伦敦大笨钟为您报时:"+subject.getTime()); } } /** * 定时任务,每秒更新一次ClockTimerSubject的状态 */ class TimerTask extends Thread{ private ClockTimerSubject timer; public TimerTask(ClockTimerSubject timer){ this.timer = timer; } @Override public void run() { while(true){ try { timer.tick(); Thread.sleep(1000); } catch (InterruptedExceptio