❤角色组成
❤抽象目标(Subject):增加观察者方法+删除观察者方法+通知所有观察者的方法。一般用一个抽象类和接口来实现。
❤抽象观察者(Observer):有一个更新方法,在得到主题通知时更新自己。(即把目标信息同步给自己)
❤具体目标(ConcreteSubject):目标信息+观察者集合。是一个具体的信息,信息状态改变后通知所有观察者(比如天气状态)
❤具体观察者(ConcreteObserver):目标信息+自己的名字+自己的工作。更新得到目标信息后通知自己可以做自己的事情了。(比如天气晴朗+A+逛街)
1.手动实现
❤抽象目标
public interface Subject {
// 添加观察者
public void add(Observer observer);
// 删除观察者
public void delete(Observer observer);
// 通知所有观察者
public void notifyObservers();
}
❤抽象观察者
public interface Observer {
// 更新目标信息
// 1.推模型,由目标推送给观察者需要的信息,按需推送,这里观察者只需要天气信息
public void update(String weatherState);
// 2.拉模型,由观察者拉取目标的整个对象
// public void update(Subject subject);
}
❤具体目标
public class ConcreteSubject implements Subject {
private String weatherState;// 目标信息
public List<Observer> observers = new ArrayList<Observer>();// 观察者集合
public String getWeatherState() {
return weatherState;
}
public void setWeatherState(String weatherState) {
this.weatherState = weatherState;
this.notifyObservers();
}
public void add(Observer observer) {
observers.add(observer);
}
public void delete(Observer observer) {
observers.remove(observer);
}
// 1.推模型
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(weatherState);// 即通过调用观察者的update方法,将目标信息更新给观察者
}
}
// 2.拉模型
// public void notifyObservers() {
// for(Observer observer : observers){
// observer.update(this);
// }
// }
}
❤具体观察者
public class ConcreteObserver implements Observer {
private String name;// 观察者名字
private String work;// 观察者想要做的事
private String weatherState;// 天气状态
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWeatherState() {
return weatherState;
}
public void setWeatherState(String weatherState) {
this.weatherState = weatherState;
}
public String getWork() {
return work;
}
public void setWork(String work) {
this.work = work;
}
// 1.推模型
public void update(String weatherState) {
System.out.println(name + "获得信息:" + weatherState + " " + work);
}
// 2.拉模型
// public void update(Subject subject) {
// weatherState = ((ConcreteSubject)subject).getWeatherState();//强转为子类
// System.out.println(name+"获得信息:"+weatherState+" "+work);
// }
}
❤测试类
public class Client {
public static void main(String[] args) {
// 1.创建目标
ConcreteSubject subject = new ConcreteSubject();
// 2.创建观察者
ConcreteObserver observerA = new ConcreteObserver();
observerA.setName("A");
observerA.setWork("出去逛街");
ConcreteObserver observerB = new ConcreteObserver();
observerB.setName("B");
observerB.setWork("出去打球");
// 3.添加观察者
subject.add(observerA);
subject.add(observerB);
// 4.目标发布信息
subject.setWeatherState("天气晴朗");
}
}
❤运行结果
A获得信息:天气晴朗 出去逛街
B获得信息:天气晴朗 出去打球
❤推模型和拉模型
推模型:目标主动向观察者推送目标的部分信息,按需推送。
拉模型:观察者主动到目标对象中获取信息,一般这种模型会把目标对象自身通过update方法传递给观察者,即拉取整个对象,复用性高。
2. 通过JDK自带的接口实现
❤具体目标(继承Obervervable类,不要在意名字)
import java.util.Observable;
public class ConcreteSubject extends Observable {
private String weatherState;
public String getWeatherState() {
return weatherState;
}
public void setWeatherState(String weatherState) {
this.weatherState = weatherState;
this.setChanged();// 开启通知,必不可少
this.notifyObservers(weatherState);// 推模型
this.notifyObservers();// 拉模型
}
}
❤具体观察者(实现Observer接口)
import java.util.Observable;
import java.util.Observer;
public class ConcreteObserver implements Observer {
private String name;
private String work;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWork() {
return work;
}
public void setWork(String work) {
this.work = work;
}
// 第一个参数是拉模型,第二个参数是推模型
@Override
public void update(Observable o, Object arg) {
System.out.println("推模型:" + name + "获得信息:" + arg + " " + work);
System.out.println("拉模型:" + name + "获得信息:"
+ ((ConcreteSubject) o).getWeatherState() + " " + work);
}
}
❤测试类
public class Client {
public static void main(String[] args) {
// 1.创建目标
ConcreteSubject subject = new ConcreteSubject();
// 2.创建观察者
ConcreteObserver observerA = new ConcreteObserver();
observerA.setName("A");
observerA.setWork("出去逛街");
ConcreteObserver observerB = new ConcreteObserver();
observerB.setName("B");
observerB.setWork("出去打球");
// 3.添加观察者
subject.addObserver(observerA); // 自带的添加方法
subject.addObserver(observerB);
// 4.目标发布信息
subject.setWeatherState("天气晴朗");
}
}
❤运行结果
推模型:B获得信息:天气晴朗 出去打球
拉模型:B获得信息:天气晴朗 出去打球
推模型:A获得信息:天气晴朗 出去逛街
拉模型:A获得信息:天气晴朗 出去逛街
❤JDK自带对比和自己实现对比
1.JDK自带抽象目标和抽象观察者不需要我们去实现,比我们自己实现代码工作量少
2.通过自己实现的方式在notifyObservers方法遍历集合的过程中通过if判断分类通知,而JDK会通知所有观察者
3.JDK具体观察者中的update方法两个参数Observable o, Object arg即拉模型和推模型,两者都支持推拉模型
❤观察者模式的优点
使目标和观察者之间解耦,原本目标改变需要依次去调用观察者通知,现在目标set新的状态自动通知,核心就是把通知观察者的方法(即update方法)放到了set方法中实现。