观察者模式定义:
它是对象的行为模式,它有叫做发布/订阅模式(redis中有这样的概念),模型/视图模式,源/监听器模式或从属模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题发生改变时,会通知所有他的观察者对象,使之跟随改变更新。
为什么会有这种设计模式呢?在一个软件生态中,对象之间依赖当一个改变时会有相应的其它对象发生改变。能完成这个问题的方案有很多,但是为了使系统能够易于复用,应选择耦合度较低的方案,减少对象之间的耦合有利于系统的复用,但是同时也应该使这些低耦合对象之间维持行动协调一致,保证高度协作。所以观察者设计模式就出现了。
它的类图如下图所示:
从类图中可观察到一下几个概念:
Subject(抽象主题)角色:首先它是一个interface,它维护的一个集合保存所有的观察者,并且提供增加和删除观察者对象和通知所有观察者对象的方法。一般他有被称为Observable(自jdk.1.0 本身库中包含这个类后面会说到)角色,一般用接口或抽象类来表示。
Observer(抽象观察者)角色:为所有具体观察者定义一个接口,在得到一个主题时通知更新自己,也叫作更新接口。他通常使用接口或抽象类实现。可看到它通常只包含一个方法(update()).
ConcreteSubject(具体主题)角色:将有关状态存入具体观察者对象,在具体主题发生改变是,给所有登记过的具体观察者发送通知。
ConcreteObserver(具体观察者)角色:存储与主题状态相关的自状态。
简单实现,代码如下:
Subject接口:
1 package com.obserable; 2 public interface Subject { 3 void addObserver(Observer observer); 4 void delObserver(Observer observer); 5 void notifyall(); 6 }
SubjectImpl实现类:
1 package com.obserable; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6 7 public class SubjectImpl implements Subject { 8 private List<Observer> list = new ArrayList<Observer>(); 9 @Override 10 public void addObserver(Observer observer) { 11 // TODO Auto-generated method stub 12 list.add(observer); 13 } 14 15 @Override 16 public void delObserver(Observer observer) { 17 // TODO Auto-generated method stub 18 list.remove(observer); 19 } 20 21 @Override 22 public void notifyall() { 23 Iterator<Observer> iter = list.iterator(); 24 while(iter.hasNext()){ 25 iter.next().update(); 26 } 27 } 28 29 }
Observer接口:
1 package com.obserable; 2 3 public interface Observer { 4 void update(); 5 }
ObserverImpl实现类:
1 package com.obserable; 2 3 public class ObserverImpl implements Observer{ 4 private String name; 5 6 public ObserverImpl(String name) { 7 super(); 8 this.name = name; 9 } 10 11 @Override 12 public void update() { 13 System.out.println(name+"I am notify"); 14 } 15 16 }
测试类:
1 package com.obserable; 2 3 public class Test { 4 public static void main(String[] args) { 5 Subject sub = new SubjectImpl(); 6 sub.addObserver(new ObserverImpl("王五")); 7 sub.addObserver(new ObserverImpl("王五1")); 8 sub.addObserver(new ObserverImpl("王五2")); 9 sub.notifyall(); 10 } 11 12 13 }
结果:
王五I am notify
王五1I am notify
王五2I am notify
还可以使用抽象类来实现Subject,Observer不变;
1 package com.obserable; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6 7 public abstract class AbstractSubjct { 8 9 private List<Observer> list = new ArrayList<Observer>(); 10 public void addObserver(Observer observer) { 11 list.add(observer); 12 } 13 14 public void delObserver(Observer observer) { 15 // TODO Auto-generated method stub 16 list.remove(observer); 17 } 18 public void notifyall() { 19 Iterator<Observer> iter = list.iterator(); 20 while(iter.hasNext()){ 21 iter.next().update(); 22 } 23 } 24 25 26 }
抽象类的实现类:
1 package com.obserable; 2 3 public class JtSubject extends AbstractSubjct{ 4 private String state; 5 6 public void change(String state){ 7 this.state=state; 8 notifyall(); 9 } 10 }
Observer不变。
测试类:
1 package com.obserable; 2 3 public class AbsTest { 4 public static void main(String[] args) { 5 JtSubject as = new JtSubject(); 6 as.addObserver(new ObserverImpl("王五")); 7 as.addObserver(new ObserverImpl("王五1")); 8 as.addObserver(new ObserverImpl("王五2")); 9 as.change("hello"); 10 } 11 }
结果:
王五I am notify
王五1I am notify
王五2I am notify
因为此模式在实际应用中广泛,所以自jdk1.0就纳入的本身库。
Observer接口,等同于上述的Observer,只有一个update方法。
1 * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. 2 package java.util; 3 4 /** 5 * A class can implement the <code>Observer</code> interface when it 6 * wants to be informed of changes in observable objects. 7 * 8 * @author Chris Warth 9 * @see java.util.Observable 10 * @since JDK1.0 11 */ 12 public interface Observer { 13 /** 14 * This method is called whenever the observed object is changed. An 15 * application calls an <tt>Observable</tt> object's 16 * <code>notifyObservers</code> method to have all the object's 17 * observers notified of the change. 18 * 19 * @param o the observable object. 20 * @param arg an argument passed to the <code>notifyObservers</code> 21 * method. 22 */ 23 void update(Observable o, Object arg); 24 }
再看jdk中Observable类,他是一个可实例化类。
1 * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. 2 3 package java.util; 4 public class Observable { 5 private boolean changed = false; 6 private Vector<Observer> obs; 7 8 /** Construct an Observable with zero Observers. */ 9 10 public Observable() { 11 obs = new Vector<>(); 12 } 13 14 15 public synchronized void addObserver(Observer o) { 16 if (o == null) 17 throw new NullPointerException(); 18 if (!obs.contains(o)) { 19 obs.addElement(o); 20 } 21 } 22 23 24 public synchronized void deleteObserver(Observer o) { 25 obs.removeElement(o); 26 } 27 28 29 public void notifyObservers() { 30 notifyObservers(null); 31 } 32 33 34 public void notifyObservers(Object arg) { 35 36 Object[] arrLocal; 37 38 synchronized (this) { 39 40 if (!changed) 41 return; 42 arrLocal = obs.toArray(); 43 clearChanged(); 44 } 45 46 for (int i = arrLocal.length-1; i>=0; i--) 47 ((Observer)arrLocal[i]).update(this, arg); 48 } 49 50 51 public synchronized void deleteObservers() { 52 obs.removeAllElements(); 53 } 54 55 protected synchronized void setChanged() { 56 changed = true; 57 } 58 59 protected synchronized void clearChanged() { 60 changed = false; 61 } 62 63 public synchronized boolean hasChanged() { 64 return changed; 65 } 66 67 public synchronized int countObservers() { 68 return obs.size(); 69 } 70 }
可以看到它是线程安全的,方法是有synchronizednchronized修饰的,而且维护的Observer集合使用的Vector。
使用方法和上述一样。