我们先思考一个问题。如果一个网站设置了天气显示的功能,而且天气显示的功能我们都是获取官网给的数据显示的。而官网的数据是不定期更新的。
我们有两种设计方案:
第一种
在网站上设置线程,线程每隔1分钟去读取官网数据,然后跟自己网站数据做比较,如果是改变了就更新。
这种设计方式看上去很合理。但是我们试想这样做的话,如果我们要获取比较频繁的数据的话,但数据又不知道什么时候会更新。这就引出了我们的第二种方案--
观察者模式也叫 发布-订阅
第二种
观察者模式当然也是遵循面向接口编程的,原理也是,我们可以订阅官网的天气数据,如果天气数据发生变化,官网会发送消息告诉自己网站“我们官网的数据更新了”,我们自己的网站接受到这条消息,自然会调用更新方法。
先看一个场景:
老板要通知同事们做事
分析:是老板作为通知类,而同事做为观察者类。
于是我们有
Subject.java接口
package com.jing.observer;
/**
* 抽象通知者类
* @author Administrator
*
*/
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
public void myNotify();
}
接着是观察者接口
package com.jing.observer;
public interface Observer {
//抽象观察者类
public void updata();
}
接着老板类实现通知者接口
SubjectBoss.java
package com.jing.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 具体通知者类
* @author Administrator
*
*/
public class SubjectBoss implements Subject{
List observers = new ArrayList();
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void myNotify() {
for(Observer oberver :observers){
oberver.updata();
}
}
}
接着实现观察者 就是同事类
ObserverSeeStock.java
package com.jing.observer;
public class ObserverSeeStock implements Observer{
@Override
public void updata() {
System.out.println("ObserverSeeStock 更新");
}
}
之后是main函数
package com.jing.observer;
public class Main {
public static void main(String[] args) {
//没有加委托的 观察者模式..
Subject boss = new SubjectBoss();//大老板 通知类
Observer seeStock = new ObserverSeeStock();//同事一 看股票 具体观察者1
Observer seeNba = new ObserverSeeNba();//同事二 看Nba 具体观察者2
Observer seeMovie = new ObserverSeeMovie();//这种是违背原则的。。。
Observer seeSky = new MyProxy();//利用代理模式 就是为了不修改ObserverSeeSky这个类
boss.attach(seeStock);//添加观察者
boss.attach(seeNba);//添加观察者
boss.attach(seeMovie);
boss.attach(seeSky);
boss.myNotify();//通知更新
}
}
ObserverSeeStock订阅了老板的通知,所以当老板用myNotify会接收到更新通知。
==========================================================
至此这就是观察者模式了。
========================================================
但是我们来分析下。如果我们要用有新的观察者时,我们就要实现Observer接口,然后实现updata方法。
package com.jing.observer;
public class ObserverSeeSky {
public void seeSky(){
System.out.println("sky updata");
}
}
这里我们来了个seeSky()方法我们是不是要修改这个类实现Observer接口
package com.jing.observer;
public class ObserverSeeMovie implements Observer{
//通过实现接口通知更新 ,但是这样的做法违背了开放封闭原则。
public void seeMovie(){
System.out.println("看电影 更新");
}
@Override
public void updata() {
seeMovie();
}
}
这样做我们可以看到这是违背的开放-封闭原则的
于是我们就有了代理模式+观察者模式的做法了
package com.jing.observer;
public class MyProxy implements Observer{
//代理ObserverSeeSky
private ObserverSeeSky observer = new ObserverSeeSky();
@Override
public void updata() {
observer.seeSky();
}
}
这个MyProxy是代理了OBserverSeeSky的,而OBserverSeeSky的方法是完全没改动的。
这也是个人的见解了,有不对的地方欢迎大家来讨论。