主要内容
1.观察者模式原理
定义:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化。通常一个Subject对象对应多个Observer对象,且Observer对象对Subject中某个状态具有一依赖性(也就是说,当Subject的某个状态变化时,Observer会执行不同的操作)
1.1 类图
1.2 角色
Subject(主题):它把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject(具体主题):将有关状态存入具体主题对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
Observer(观察者):观察者父类。
ConcreteObserver(具体观察者):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
2.观察者模式示例
2.1 背景(过红绿灯)
Subject:主题为红绿灯
Observer:观察者为车和认
2.2 代码
2.2.1 Subject(抽象类)
该类定义了对观察者对象集合的处理操作
public abstract class Subject {
//观察者对象引用的集合
private List<Observer> observers = new ArrayList<Observer>();
//添加监视器
public void attach(Observer observer) {
if (observer == null) {
return;
}
observers.add(observer);
}
//删除监视器
public void detach(Observer observer) {
Iterator<Observer> iterator = observers.iterator();
while (iterator.hasNext()) {
Observer next = iterator.next();
if (observer.equals(next)) {
iterator.remove();
}
}
}
//通知观察者(该应用中特指:通知观察者(人或者车)通行)
public void notifyObserver() {
for (Observer observer : observers) {
observer.deal(this);
}
}
}
2.2.2 ConcreteSubjectTrafficLights(红绿灯)
该类定义了自身一些状态信息,这特指红绿灯的颜色(红和绿)
public class ConcreteSubjectTrafficLights extends Subject{
//红灯停,绿灯行,黄灯缓
private String color = "red";
public String getColor() {
return color;
}
//更新红绿灯的颜色,红或者绿
public void update(String color){
this.color = color;
}
}
2.2.3 Observer(抽象观察者)
public interface Observer {
public void deal(Object o);
}
2.2.4 ConcreteObserverMan(观察者人)
public class ConcreteObserverMan implements Observer {
public void deal(Object o) {
if(o instanceof ConcreteSubjectTrafficLights){
String color = ((ConcreteSubjectTrafficLights) o).getColor();
if(color.equalsIgnoreCase("red")){
System.out.println("man 步行过马路");
}else{
System.out.println("man 等灯变绿");
}
}
}
}
2.2.5 ConcreteObserverCar(观察者车)
public class ConcreteObserverCar implements Observer{
public void deal(Object o) {
if(o instanceof ConcreteSubjectTrafficLights){
String color = ((ConcreteSubjectTrafficLights) o).getColor();
if(color.equalsIgnoreCase("red")){
System.out.println("car 正常通行");
}else{
System.out.println("car 等灯变绿");
}
}
}
}
2.2.6 Client(测试与使用)
public class Client {
public static void main(String[] args) {
//具体的红绿灯对象(Subject)
ConcreteSubjectTrafficLights subject = new ConcreteSubjectTrafficLights();
ConcreteObserverCar concreteObserverCar = new ConcreteObserverCar();
ConcreteObserverMan concreteObserverMan = new ConcreteObserverMan();
subject.attach(concreteObserverCar);
subject.attach(concreteObserverMan);
System.out.println("_____________init_____________");
//初始状态通知观察红绿灯的具体观察者(人和车)
subject.notifyObserver();
System.out.println("__________color change________");
//具体对象状态变化(红绿灯,灯颜色变化了)
subject.update("green");
//再次通知观察红绿灯的具体观察者(人和车)
subject.notifyObserver();
System.out.println("__detach concreteObserverMan___");
//移除某个观察者
subject.detach(concreteObserverMan);
//再次发通知
subject.notifyObserver();
}
}
output
_____________init_____________
car 正常通行
man 步行过马路
__________color change________
car 等灯变绿
man 等灯变绿
__detach concreteObserverMan___
car 等灯变绿
通过以上的代码示例及注释,相信你对观察者模式有了一个比较清晰的认识,这边建议你再回头看一下1.2 角色,就会有更深入的理解。
3.JDK观察者模式
JDK内建了观察者模式的相关支持类
3.1 Observable(等价Subject,被观察者)
package:java.util.Observable
相比于我们自己写的Subject抽象类,它采用了Vector作为观察者集合对象
同样的Observable其中也定义了一些操作观察者集合的方法,方法比较简单,这些方法大都采用同步的方式实现。
3.2 Observer(观察者)
package:java.util.Observer
/**
* A class can implement the <code>Observer</code> interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
以上摘自jdk源码,定义了观察者的updata方法
第一个参数Observable o,表示被观察者对象
第二个参数Object arg,表示Observable对象的notifyObservers方法的参数
4.小结
观察者模式通过1对n的组合形式将被观察者的状态变化同步到观察者中,观察者根据被观察者的状态执行具体的处理逻辑。
优点:观察者和主题对象松耦合,两者可以先对独立的扩展和变化,比如可以很方便的增删观察者,修改观察者中的更新逻辑而不用修改主题中的代码。
缺点:
1.Subject(抽象主题)需要依赖Observer(抽象观察者),而这种依赖关系完全可以去除。
2.主题需要维护观察者列表,并对外提供动态增删观察者的接口,
3.主题状态改变时需要由自己去通知观察者进行更新。