概述
本文主要介绍观察者模式,通过栗子和代码简明的说明其原理.
引文
java 有很多种设计模式,主要的有GOF的23种,关于设计模式其实我们不必感到彷徨,觉得不懂、高端,其实这些规律都来源于我们的生活.
设计模式其实是very的easy的,今天要讲的是观察者模式,如果你是一个developer,但是不太明白什么是观察者模式,听完这个故事你就明白了.
故事之观察者模式-相对论
我想想举个什么栗子合适呢….waiting…,ok ,比如中国的皇帝总是让子民提供好东西,皇帝需要18岁的妹纸当后宫储备,或者18岁的男性当侍卫储备…或者山珍海味,但是下层的人民只有知道皇帝需要什么才会去准备,没有的自然就提供不了;这时候皇帝会发诏书给下层官员,下层官员又下发命令给人民。这里有两个过程皇帝下令给官员,官员下发命令给人民,这样就有了观察者模式。
观察者和被观察者,观察者就是一直等着被观察者发布命令,比如官员相对皇帝,官员是观察者,皇帝是被观察者,官员等着皇帝的命令;人民相对官员,人民是观察者,官员是被观察者,人民等着官员发布命令,这样一个故事中就包含了两个观察者模式,观察者和被观察者是相对的。
观察者始终等待着被观察者发布命令,此时被观察者的下属都会受到这个消息,至于执不执行这个消息,由观察者自己定.如果你是开发人员,请再看一个实际栗子。
假设CLASS A 是接收数据的(数据类型有B C D两种),CLASS B C是处理数据,但是B C 不一样,B只处理B类型数据,C只处理C类型数据,此时用观察者模式来实现就是CLASS A 作为被观察者,CLASS B C 作为观察者,当A中MESSAGE消息到达时, B C 都会受到消息MESSAGE,但具体是忽略这个消息还是处理这个消息都是由B C 自己决定.这就是一个观察者模式的简单实现.
代码实例
1. 定义主题接口-皇帝
package observer;
public interface Subject {
//添加观察者
void addObserver(Observer obj);
//移除观察者
void deleteObserver(Observer obj);
//当主题方法改变时,这个方法被调用,通知所有的观察者
void notifyObserver();
}
2. 定义观察者接口-皇帝下属的官员
package observer;
public interface Observer {
//当主题状态改变时,更新通知
public void update(String kingName, String kingDemand);
}
3. 主题的实现类-中国的皇帝
官员由皇帝管理.
package observer;
import java.util.ArrayList;
import java.util.List;
public class ChinaKingDemandSubject implements Subject{
//存放订阅者
private List<Observer> observers = new ArrayList<Observer>();
//皇帝的需求
private String kingDemand;
//皇帝的名字
private String kingName;
public ChinaKingDemandSubject(String kingName){
this.kingName = kingName;
}
public String getKingName(){
return this.kingName;
}
@Override
public void addObserver(Observer obj) {//将观察者和被观察者绑定,也可以理解为订阅
observers.add(obj);
}
@Override
public void deleteObserver(Observer obj) {
int i = observers.indexOf(obj);
if (i >= 0){
observers.remove(obj);
}
}
@Override
public void notifyObserver(String kingName, String kingDemand) {//**注意** 此方法会循环调用ArrayList,通知所有的观察者,有消息来了.
for (int i=0;i<observers.size();i++) {
Observer o = (Observer)observers.get(i);
o.update(kingName, kingDemand);
}
}
//皇帝发布新命令,征集美女或者壮士
public void publish(String kingName, String kingDemand){
//新版本
this.kingDemand = kingDemand;
//**注意** 信息更新完毕,通知所有观察者,比如官员去执行命令找到合适的人并送进宫中
notifyObserver(kingName, kingDemand);
}
}
4. 观察者实现类-中国皇帝的下属官员
官员给皇帝找需要的东西.
package observer;
// 此时的观察者就是官员,官员有很多,各地的地方官都有
public class ChinaOfficialObserver implements Observer{
//订阅者名字
private String name;
private String kingDemand;
public ChinaOfficialObserver(String name){
this.name = name;
}
@Override
public void update(String kingName, String kingDemand) {
this.kingDemand = kingDemand;
System.out.println(kingName + "来了命令,找" + kingDemand);
this.found(kingDemand);
}
public void found(String kingName, String kingDemand){
System.out.println("官员" + name + "找到了" + kingName + "需要的" + kingDemand);
}
}
5. 中国皇帝的需求
package observer;
public class Main{
public static void main(String[] args) {
//创建主题(被观察者)
ChinaKingDemandSubject chinaKingDemand = new ChinaKingDemandSubject("中国皇帝");
//创建三个不同的观察者
ChinaOfficialObserver a = new ChinaOfficialObserver("长安地方官");
ChinaOfficialObserver b = new ChinaOfficialObserver("台湾地方官");
ChinaOfficialObserver c = new ChinaOfficialObserver("广州地方官");
//将观察者注册到主题中
chinaKingDemand.addObserver(a);
chinaKingDemand.addObserver(b);
chinaKingDemand.addObserver(c);
//更新主题的数据,当数据更新后,会自动通知所有已注册的观察者
chinaKingDemand.publish(chinaKingDemand.getKingName(), "大于18岁单身的绝世美女");
System.out.println("----------hold on ... king need -----------");
chinaKingDemand.publish(chinaKingDemand.getKingName(), "大于18岁力能扛鼎的壮汉");
}
}
6. 运行结果
中国皇帝来了命令,找大于18岁单身的绝世美女.
官员长安地方官找到了中国皇帝需要的大于18岁单身的绝世美女.
中国皇帝来了命令,找大于18岁单身的绝世美女.
官员台湾地方官找到了中国皇帝皇帝需要的大于18岁单身的绝世美女.
中国皇帝来了命令,找大于18岁单身的绝世美女.
官员广州地方官找到了中国皇帝皇帝需要的大于18岁单身的绝世美女.
———-hold on … king need ———–
中国皇帝来了命令,找大于18岁力能扛鼎的壮汉.
官员长安地方官找到了中国皇帝皇帝需要的大于18岁力能扛鼎的壮汉.
中国皇帝来了命令,找大于18岁力能扛鼎的壮汉.
官员台湾地方官找到了中国皇帝皇帝需要的大于18岁力能扛鼎的壮汉.
中国皇帝来了命令,找大于18岁力能扛鼎的壮汉.
官员广州地方官找到了中国皇帝皇帝需要的大于18岁力能扛鼎的壮汉.
总结
无论是观察者模式还是其他设计模式都是人们对真实生活应用场景的总结,细细品味,便会发现其中的精髓.