观察者(Observer)模式----------发送状态变化通知
》》在 Observer 模式中,当观察对象的状态发生变化时,会通知
给观察者。Observer 模式适用于根据对象状态进行相应处理的
场景。
-------------------示例程序:是一个简单的示例程序,观察者将观察
一个会生成数值的对象,并将它生成的数值结果显示出来。不过,
不同的观察者的显示方式不一样。DigitObserver 会以数字形式
显示数值,而 GraphObserver 则会以简单的图示形式来显示数值。
》》示例程序的类图:
》》Observer 接口:
package observer;
/*
* 该接口表示的是“观察者”的接口。
* 与 Java 类库中的 java.util.Observer 接口不同
*/
public interface Observer {
public abstract void update(NumberGenerator generator);
}
》》NumberGenerator 类:
package observer;
import java.util.ArrayList;
import java.util.Iterator;
/*
* 该类是表示用于生成数值的抽象类
*/
public abstract class NumberGenerator {
//保存有观察 NumberGenerator 的 Observer 们
private ArrayList observers = new ArrayList();
//注册 Observer
public void addObserver(Observer observer){
observers.add(observer);
}
//删除 Observer
public void deleteObserver(Observer observer){
observers.remove(observer);
}
//向 Observer 发送通知
public void notifyObservers(){
Iterator it = observers.iterator();
while(it.hasNext()){
Observer h = (Observer)it.next();
h.update(this);
}
}
//获取数值
public abstract int getNumber();
//生成数值
public abstract void execute();
}
》》RandomNumberGenerator 类:
package observer;
import java.util.Random;
public class RandomNumberGenerator extends NumberGenerator {
//随机数生成器
private Random random = new Random();
//当前数值
private int number;
// 用于获取 number 字段的值
public int getNumber() {
return number;
}
//会生成20个随机数(0~49的整数)
public void execute() {
for(int i = 0 ; i < 20 ; i++){
number = random.nextInt(50);
notifyObservers();
}
}
}
》》DigitObserver 类--》具体的观察者之一
package observer;
/*
*该观察者的功能是以数字形式显示观察到的数值
*/
public class DigitObserver implements Observer {
@Override
public void update(NumberGenerator generator) {
System.out.println("DigitObserver:"+generator.getNumber());
try{
Thread.sleep(100);
}catch(InterruptedException e){
}
}
}
》》GraphObserver 类 --》具体的观察者之一
package observer;
public class GraphObserver implements Observer {
@Override
public void update(NumberGenerator generator) {
System.out.print("GraphObserver:");
int count = generator.getNumber();
for(int i = 0 ; i < count ; i++){
System.out.print("*");
}
System.out.println("");
try{
Thread.sleep(100);
}catch(InterruptedException e){
}
}
}
》》Main 类 ---》测试程序
package observer;
public class Main {
public static void main(String[] args){
RandomNumberGenerator generator = new RandomNumberGenerator();
Observer observer1 = new DigitObserver();
Observer observer2 = new GraphObserver();
generator.addObserver(observer1);
generator.addObserver(observer2);
generator.execute();
}
}
-----------------------------------------------------------------------------
《程序运行结果》(一部分)
----------------------------------------------------------------------------
《Observer模式中的登场角色》
**** Subject (观察对象)
Subject 角色表示观察对象。Subject 角色定义了注册观察者和删除观察者
的方法。此外,它还声明了“获取现在的状态”的方法。在示例程序中,由
NumberGenerator 类扮演此角色。
**** ConcreteSubject (具体的观察者对象)
ConcreteSubject 角色表示具体的被观察者对象。当自身状态发生变换后,
它会通知所有已经注册的 Observer 角色。在示例程序中,由
RandomNumberGenerator 类扮演此角色。
**** Observer (观察者)
Observer 角色负责接收来自 Subject 角色的状态变化的通知。为此,
声明了 update 方法。在示例程序中,由 Observer 接口扮演此角色。
**** ConcreteObserver (具体的观察者)
ConcreteObserver 角色表示具体的 Observer 。当它的 update 方法被
调用后,会去获取要观察的对象的最新的状态。在示例程序中,由
DigitObserver 类和 GraphObserver 类扮演此角色。
-------------------------------------------------------------
《扩展思路的要点》
1.这里也出现了可替换性
可替换性的思想:
(1)、利用抽象类和接口从具体类中抽出抽象方法
(2)、在将实例作为参数传递至类中,或者类的字段中
保存实例时,不使用具体的类型,而是使用抽象
类型和接口
《上面的实现方式可以帮助我们轻松地替换具体类》
2.Observer 的顺序
3.当 Observer 的行为会对 Subject 产生影响时
4.传递更新信息的方式
5.从“观察”变为“通知”
在上面的程序中, Observer 观察者是被动地接收来自
Subject 角色的通知。因此 Observer 模式,也被称为
"发布---订阅"模式
6.Model / View / Controller (MVC)
MVC 中的 Model 和 view 的关系与 Subject 角色和
Observer 角色 的关系相对应。Model 是指操作
“不依赖显示形式的内部模型”的部分,View 则是管理
Model “怎样显示”的部分。通常情况下,一个Model
对应多个 View 。
----------------------------------------------------------------
《相关的设计模式》
1. Mediator 模式