设计模式之——观察者模式
Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
典型应用
- 侦听事件驱动程序设计中的外部事件
- 侦听/监视某个对象的状态变化
- 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者
- 多线程编程上下游线程协作,即通常所说的一个线程需要等待其它的线程完成某些动作后才能执行。 a. JDK自带的CountDownLatch、CyclicBarrier、SemaPhore、Executor、CompletionService都可以达到相同的效果。 b. 这里面不令人满意的效果是CountDownLatch、CyclicBarrier、SemaPhore都需要等待所有"下游线程(同性质的其它线程)"完成才会执行等待操作后面的任务,导致线程资源浪费。 c. 执行器相对前面几个效果更好,下游线程不用关心其它下游线程是否完成不会造成等待现象,不过上游线程需要重复获取所有下游线程的状态,直到所有下游线程完成。 d. Jdk为解决这个问题提供了CompleteionService和ExecutorCompleteionService来解决执行器重复获取下游线程的问题,这种方式最为优雅、完美)。
Observer模式的优点
- 对象之间可以进行同步通信
- 可以同时通知一到多个关联对象
- 对象之间的关系以松耦合的形式组合,互不依赖
Observer模式的结构
- JDK1.2后,Java提供了对观察者模式的支持接口和实现类。其中接口 java.util.Observer 用来指定观察者,观察者必须实现 void update(Observable o, Object arg) 方法。而 java.util.Observable 用来指定观察物(被观察者、可被观察的),并且提供了一系列的方法,可以很轻易的使用这个接口和实现类来实现观察者模式。
- java.util.Observer 只有一个简单的方法 void update(Observable o, Object arg)。其中,参数 Observable o 用于指定触发 update 方法的对象, Object arg 用于指定触发 update 方法时候的附加参数。
Observer模式的例子
-
/** * 观察者模式 *
* 被观察的对象。即被观察者监视的对象 *
* * @author wangcong * @data 2016年6月6日下午3:26:01 */public class PayTask extends Observable { //支付 public void pay() { System.out.printf("支付指令被调用...\n"); setChanged(); notifyObservers(); }}/** * 观察者模式 *
* 具体的观察者。即:当被观察的对象状态发生变化后,需要做出相应变化或处理的对象 *
* * @author wangcong * @data 2016年6月6日下午3:21:29 */public class PayObserver implements Observer { @Override public void update(Observable o, Object arg) { System.out.printf("发现支付指令被调用,通知客户请求已提交至银行\n"); }}
Observer模式的多线程应用
一个简单的例子:
/** * 观察者模式 ** 被观察的对象。即被观察者监视的对象 *
* * @author wangcong * @data 2016年6月6日下午3:26:01 */public class PayTask extends Observable implements Runnable { // 支付 public void pay() { System.out.printf("%s,支付指令被调用...\n", Thread.currentThread().getName()); setChanged(); notifyObservers(); } @Override public void run() { // 为了好查看效果,此处休眠下 long duration = (long) (Math.random() * 10); try { TimeUnit.SECONDS.sleep(duration); System.out.printf("%s, sleep %d \n", Thread.currentThread().getName(), duration); } catch (InterruptedException e) { e.printStackTrace();// 此处不作处理 } this.pay(); }}
/** * 观察者模式 ** 具体的观察者。即:当被观察的对象状态发生变化后,需要做出相应变化或处理的对象 *
* * @author wangcong * @data 2016年6月6日下午3:21:29 */public class PayObserver implements Observer { // 等待多少线程完成 private int totalCount = 0; private AtomicInteger countNum = null; public PayObserver(int count) { this.totalCount = count; countNum = new AtomicInteger(count); } @Override public void update(Observable o, Object arg) { int count = countNum.decrementAndGet(); if (0 == count) { // 处理后续流程 System.out.printf("所有数据都已调用支付指令,通知客户请求已提交至银行\n"); } else { // no-thing to do System.out.printf("应该有%d协作线程,还有%d线程未完成\n", totalCount, countNum.get()); } }}
public class Client { public static void main(String[] args) { // 数据校要 // 创建后续业务处理类 PayObserver po = new PayObserver(10); // 创建支付线程 for (int i = 0; i < 10; i++) { PayTask bt = new PayTask(); bt.addObserver(po); // 添加观察者 Thread t = new Thread(bt, "pay-" + i); t.start(); } }}
运行结果: