使用场景
观察者模式应用在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知。
状态会改变的对象被称为“Subject主题”,观察者们被称为“Observer”.
一个主题可以不断地加入新的观察者,也可以剔除掉观察者。
场景比如:
1、根据天气变化,学校要决定是否上课,同时通知给所有的学生。学校可以新增学生,也可以开除学生。
2、拍卖师在拍卖过程中,要不断地更新最高拍卖价,通知给所有的竞价者。竞价者可参与,可退出。
代码案例
Subject.java 主题的接口(不同于Java自带的Observable)
interface Subject{
void addObserver(Observer ob);
void deleteObserver(Observer ob);
void notifyObserver();
}
Observer.java 观察者的接口
interface Observer{
void update(Object arg);
}
display.java 观察者的行为接口
interface display{
void display();
}
School.java
class School implements Subject{
private ArrayList<Observer> observers;
private String message;
public School() {
observers = new ArrayList<>();
message = new String("明天要上课");
}
@Override
public void addObserver(Observer ob) {
observers.add(ob);
}
@Override
public void deleteObserver(Observer ob) {
if (observers.contains(ob)) {
observers.remove(ob);
}
}
@Override
public void notifyObserver() {
for (Observer ob : observers) {
ob.update(message);
}
}
public void measurementsChanged() {
notifyObserver();
}
public void setMessage(String arg) {
message = arg;
measurementsChanged();
}
}
Student.java
class Student implements Observer, display {
private String name;
private String message;
public Student(String name, Subject subject) {
this.name = name;
subject.addObserver(this);
}
@Override
public void update(Object arg) {
message = (String) arg;
display();
}
@Override
public void display() {
System.out.println(name + message);
}
}
测试类
public class MainTest {
public static void main(String[] args) {
School suda = new School();
Student a = new Student("小明", suda);
Student b = new Student("小红", suda);
Student c = new Student("小兰", suda);
suda.setMessage("放寒假了");
suda.setMessage("开学了");
}
}
输出
设计原则
1、找出程序中会变化的方面,然后将其和固定不变的方面相分离。
在观察者模式中,改变的始终是主题方面的状态信息,以及观察者的数目。比如在学校 – 学生这个场景中,我们可以改变依赖于学校对象的学生,动态地决定是否增加减少某一学生同时不会影响到学校(主题)。
2、针对接口编程,不针对实现编程
主题 和 观察者都使用接口来做,观察者利用主题的接口向主题注册自己,主题利用观察者的接口用来通知所有的观察者状态变化。达到松耦合的目的。
3、多用组合,少用继承
该模式利用组合将很多观察者组合(加入容器)进主题中,这种关系并不是由继承所实现的。