设计模式原则
- 不变的和变化的分开。
- 针对接口编程,而不针对实现编程。
- 多考虑组合,而不是继承。
- 为了交互对象之间的松耦合设计而努力。
观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
例:
- 我们有一个主题,主题里有我们要推送的内容。
- 我们有两个观察者,我们一个观察者要计算均值,并展示,一个观察者要输出数据的变化。
- 观察者想要获取主题推送的消息我们要先订阅主题的推送功能。
PS: 主题一对多中的一方,负责在数据变化的时候推送至观察者。观察者接受消息的一方。
设计思想
- 考虑第一条设计原则,那么我们要考虑,如何来划分接口内容。PS 这里我们会变化的只有数据,不变的有 1 添加订阅 2 删除订阅 3 推送消息
- 考虑第二条设计原,针对接口编程而不针对实现编程,那么我们需要一个接口提供1中的3个方法,这个是针对主题的,而对于所有的观察者我们都需要一个接口来接受主题推送的数据。
总结: 根据上述所说我们现在共有:
- 主题类
- 主题接口
- 2个观察者类
- 1个更新接口
类设计如下
主题接口
public interface Subject {
void addObserver(Observer observer);
void deleteObserver(Observer observer);
void notifyObserver(WeatherData.Obj obj);
}
主题类
public class WeatherData implements Subject{
private List<Observer> list;
// list 订阅列表
public WeatherData(){
list = new ArrayList<Observer>();
}
@Override
public void addObserver(Observer observer) {
list.add(observer);
}
@Override
public void deleteObserver(Observer observer) {
int i = list.indexOf(observer);
if(i>=0){
list.remove(i);
}
}
@Override
public void notifyObserver(Obj obj) {
for (Observer observer : list) {
observer.update(obj);
}
}
public void measurementsChanged(Obj obj){
notifyObserver(obj);
}
// 用于更新数据变化
static class Obj{
private int i;
private int j;
public int getI() {
return i;
}
public int getJ() {
return j;
}
public void setI(int i) {
this.i = i;
}
public void setJ(int j) {
this.j = j;
}
}
}
观察者接口
public interface Observer {
public void update(Object obj);
}
统计类
public class StatisticsData implements Observer{
private WeatherData.Obj ob ;
private List<WeatherData.Obj> is ;
public StatisticsData(){
is = new ArrayList<WeatherData.Obj>();
}
@Override
public void update(Object obj) {
ob = (WeatherData.Obj) obj;
is.add(ob);
iii();
}
public void iii(){
int sumi = 0;
int sumj = 0;
for (WeatherData.Obj ob : is){
sumi +=ob.getI();
sumj +=ob.getJ();
}
System.out.println(String.format("sumi = %s , sumj = %s ,avgi = %s , avgj = %s",sumi,sumj,sumi/is.size(),sumj/is.size()));
}
}
数据类
public class Data implements Observer{
@Override
public void update(Object obj) {
WeatherData.Obj ob = (WeatherData.Obj) obj;
System.out.println(ob.getI() + " " + ob.getJ());
}
}
测试类
public class Test {
static StatisticsData statisticsData = new StatisticsData();
static Data data = new Data();
static WeatherData weatherData = new WeatherData();
public Test(){
}
public static void main(String[] args) {
weatherData.addObserver(statisticsData); // 向订阅者内增加 订阅者
weatherData.addObserver(data);
for (int i = 0 ; i<5 ; i ++){
WeatherData.Obj obj = new WeatherData.Obj();
obj.setI(i);
obj.setJ(i+1);
weatherData.measurementsChanged(obj);
weatherData.deleteObserver(data);
}
}
}
测试结果
PS: 使用接口是为了解耦合,便于变化。
PS: jvm 中提供了 观察者模式接口,可以 观察者拉取数据变化也支持推送
java.util.Observer(观察者接口);
java.util.Observable(主题类);
有兴趣的可以了解一下
提示 jvm的观察者类中提供了
这个方法,当数据变化的时候不主动调用 setChanged 方法 消息将不会推送,其他与上述基本一致。