观察者模式
来源:互联网 发布:小号软件 编辑:程序博客网 时间:2024/06/08 09:36
解决的问题:当一个类的状态变化需要通知多个类,且被通知的类型要动态变化时,就可以使用观察者模式。
标准定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。
类结构图如下:
类图中Observable类是被观察者,Observer接口为观察者定义了规范方法,该方法由被观察者进行通知。观察者模式遵循迪米特原则,被观察者通过Observer接口感知观察者,无需关心具体的观察者有哪些类型,将观察者与被观察者解耦。
Observable和Observer已集成在JDK中。在使用中,通过继承Observable创建被观察者;通过实现Observer接口定义观察者。下面先看一个航班起飞通知的例子:
//被观察者public class FlightNotice extends Observable { private String no; private Date date; FlightNotice(String no,Date date) { super(); this.no = no; this.date = date; NoticeSystem.getInstance().addSource(this); } public void addPassenger(Passenger passenger) { super.addObserver(passenger); } public void noticeAll() { super.setChanged();//设置状态变化 super.notifyObservers();//通知观察者 } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; }}
//观察者public class Passenger implements Observer{ private String name; public Passenger(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void register(String flightNo) { FlightNotice flightNotice = NoticeSystem.getInstance().getNotice(flightNo); if (flightNotice != null) { flightNotice.addPassenger(this); } } @Override public void update(Observable o, Object arg) { FlightNotice notice = (FlightNotice) o; System.out.println("dear " + name); System.out.println("flight " + notice.getNo() + " will leave at " + DateFormatUtils.format(notice.getDate(), DateFormatUtils.ISO_DATETIME_FORMAT.getPattern())); }}
//通知管理public class NoticeSystem { private static final NoticeSystem register = new NoticeSystem(); private Map<String, FlightNotice> flightNoticeMap = Maps.newHashMap(); private NoticeSystem() { } public static NoticeSystem getInstance() { return register; } public void addSource(FlightNotice flightNotice) { this.flightNoticeMap.put(flightNotice.getNo(), flightNotice); } public FlightNotice getNotice(String no) { return flightNoticeMap.get(no); }}
public class TestObserver { public static void main(String[] args) { FlightNotice notice = new FlightNotice("sz100-1", new Date()); Passenger cds = new Passenger("cds"); Passenger niko = new Passenger("niko"); cds.register("sz100-1"); niko.register("sz100-1"); notice.noticeAll(); }}输出如下:dear nikoflight sz100-1 will leave at 2017-06-23T21:04:32dear cdsflight sz100-1 will leave at 2017-06-23T21:04:32
在上述代码中,FlightNotice是被观察者,Passenger是观察者,NoticeSystem是通知管理器,管理所有被观察者。
创建一个FlightNotice即定义一个主题,放入到通知管理器中;观察者通过register决定自己要订阅的主题;当主题状态变化时,通过notifyObservers通知所有观察者。
以下是Observal源码:
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); } /** * If this object has changed, as indicated by the * <code>hasChanged</code> method, then notify all of its observers * and then call the <code>clearChanged</code> method to indicate * that this object has no longer changed. * <p> * Each observer has its <code>update</code> method called with two * arguments: this observable object and the <code>arg</code> argument. * */ public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ Object[] arrLocal; synchronized (this) { /* We don't want the Observer doing callbacks into * arbitrary code while holding its own Monitor. * The code where we extract each Observable from * the Vector and store the state of the Observer * needs synchronization, but notifying observers * does not (should not). The worst result of any * potential race-condition here is that: * 1) a newly-added Observer will miss a * notification in progress * 2) a recently unregistered Observer will be * wrongly notified when it doesn't care */ 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(); }}
阅读全文
0 0
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- iOS 友盟分享小技巧
- 如何使用JavaScript构建机器学习模型
- KL散度(Kullback-Leibler_divergence)
- 在 CentOS6.8 下配置安装部署FastDFS5.05+Nginx模块上传测试
- tiny-cnn开源库的使用(MNIST)
- 观察者模式
- Windows内核对象
- c++设计模式之访问者模式
- 关于JSch的问题描述
- MVC的基本认知
- ScheduledThreadPoolExecutor使用指南
- js实现图片滚动效果
- Django-ORM基础操作
- 使用python(一)