1、引入
Observer,译为观察者,观测者。
而在Observer模式中,当被观测对象发生改变时,观测者会得知改变并且对其进行相关反应,这种改变的得知是由被观测对象反映给观测者的。
2、示例
实现以下功能,被观测者会随机产生数字,两个观测者能够分别以数字和图形的方式在得知后展示随机数字。
2.1、被观测者-随机数字生产类
2.1.1、数字生产抽象父类
public abstract class NumberGenerator {
private ArrayList<Observer> observers=new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer o : observers) {
o.update(this);
}
}
public abstract int getNumber();
public abstract void execute();
}
2.1.2、随机数字生产子类
public class RandomNumberGenerator extends NumberGenerator{
private Random random=new Random();
int number;
@Override
public int getNumber() {
return number;
}
@Override
public void execute() {
for (int i = 0; i < 20; i++) {
number=random.nextInt(50);
notifyObservers();
}
}
}
2.2、观测者
2.2.1、观察者统一接口
public interface Observer {
public abstract void update(NumberGenerator generator);
}
2.2.2、数字观察者
public class DigitObserver implements Observer{
@Override
public void update(NumberGenerator generator) {
System.out.println("DigitObserver:"+generator.getNumber());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2.3、图形观测者
public class GraphObserver implements Observer{
@Override
public void update(NumberGenerator generator) {
System.out.println("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) {
e.printStackTrace();
}
}
}
2.3、测试
public class Main {
public static void main(String[] args) {
NumberGenerator generator = new RandomNumberGenerator();
//添加观测者
generator.addObserver(new DigitObserver());
generator.addObserver(new GraphObserver());
//随机生成数字
generator.execute();
}
}
运行结果(部分):
3、tips
- 观察?通知?:从上例来看,与其说是观测,不如说是被观测者主动通知观测者发送了变化比较合适。
- 组件化:RandomNumberGenerator并不知道随在观察它,但是所有观测者都实现了Observer接口,只需要通过notifyObservers()方法来调用观测者们的update()方法;同样的,Observer们不知道自己在检测谁,但是生产数字的类都继承了NumberGenerator抽象类,调用update()时只需要调用抽象类的getNumber()方法即可。这样做的好处是在实际生产中可以灵活拼接被观测者和观测者,实现了组件化。