java观察者模式实现和java观察者模式演化
简单的观察者模式实现
import java.util.arraylist;
import java.util.collections;
import java.util.iterator;
import java.util.list;
/**
* 观察者模式中用到了回调:
* a. 观察者将自己注册到被观察者的监听者列表,且观察者类自身提供了一个回调函数
* b. 被观察者(observable或subject)维护观察者列表,并且可以注册和解注册观察者
* c. 一旦被观察者状态发生改变,它可以调用notifyobservers(),这个方法将遍历观察者列表并逐个调用
观察者提供的回调函数
* @author will
*
*/
public class simpleobserverpattern {
public static void main(string[] args) {
simpleobserverpattern sop = new simpleobserverpattern();
list<iobserver> observers = new arraylist<iobserver> ();
iobserver observera = sop.new observer("observera");
iobserver observerb = sop.new observer("observerb");
observers.add(observera);
observers.add(observerb);
iobservable observable = sop.new observable(observers);
observable.registerobserver(sop.new observer("observerc"));
observable.changestate();
observable.close();
}
// 被观察者,有的地方叫subject
interface iobservable {
void registerobserver(iobserver observer);
void unregisterobserver(iobserver observer);
void notifyobservers();
string getstate();
void changestate();
void close();
}
class observable implements iobservable {
private static final string new = "new";
private static final string changed = "changed";
private static final string closed = "closed";
private string state;
private list<iobserver> observers;
public observable() {
this(null);
}
public observable(list<iobserver> observers) {
if(observers == null) {
observers = new arraylist<iobserver> ();
}
this.observers = collections.synchronizedlist(observers);
this.state = new;
}
@override
public void registerobserver(iobserver observer) {
observers.add(observer);
}
@override
public void unregisterobserver(iobserver observer) {
observers.remove(observer);
}
@override
public void notifyobservers() {
iterator<iobserver> iter = observers.iterator();
while(iter.hasnext()) {
iter.next().update(this);
}
}
@override
public string getstate() {
return state;
}
@override
public void changestate() {
this.state = changed;
notifyobservers();
}
@override
public void close() {
this.state = closed;
notifyobservers();
}
}
interface iobserver {
void update(iobservable observalbe);
}
class observer implements iobserver {
private string name;
public observer(string name) {
this.name = name;
}
@override
public void update(iobservable observalbe) {
system.out.println(
string.format("%s receive observalbe's change, current observalbe's state is %s",
name, observalbe.getstate()));
}
}
}
上面的实现直接将被观察者对象作为回调函数参数,这样做很不优雅,在简单的场景可能奏效。
但事实上更多情况下,一个被观察者有很多种事件或者状态,而每个观察者可能感兴趣的事件或状态都不相同,或者为了信息隐藏的目的,不想让每个观察者都能访问到observable内部的所有状态。
这样我继续演化代码为下面这个版本,注意我这里没有很细致地考虑并发问题。
import java.util.collections;
import java.util.hashset;
import java.util.hashtable;
import java.util.iterator;
import java.util.set;
public class multieventobserverpattern {
public static void main(string[] args) {
multieventobserverpattern meop = new multieventobserverpattern();
iobservable observable = meop.new observable();
iobserver observera = meop.new observer("observera");
iobserver observerb = meop.new observer("observerb");
// 注册感兴趣的事件
observable.registerobserver(observable.geteventa(), observera);
observable.registerobserver(observable.geteventb(), observerb);
// 改变被观察者状态
observable.changestatea();
observable.changestateb();
}
interface ievent {
void eventchange();
string getstate();
}
class eventa implements ievent {
private static final string initialized = "initialized";
private static final string pending = "pending";
private string state;
public eventa() {
this.state = initialized;
}
@override
public void eventchange() {
system.out.println("eventa change");
this.state = pending;
}
@override
public string tostring() {
return "eventa";
}
@override
public string getstate() {
return state;
}
}
class eventb implements ievent {
private static final string new = "new";
private static final string idle = "idle";
private string state;
public eventb() {
this.state = new;
}
@override
public void eventchange() {
system.out.println("eventb change");
this.state = idle;
}
@override
public string tostring() {
return "eventb";
}
@override
public string getstate() {
return state;
}
}
// 被观察者(observable),有的地方叫subject
interface iobservable {
void registerobserver(ievent event, iobserver observer);
void unregisterobserver(ievent event, iobserver observer);
// 通知观察者某个事件发生了
void notifyobservers(ievent event);
void changestatea();
void changestateb();
ievent geteventa();
ievent geteventb();
}
class observable implements iobservable {
private ievent eventa;
private ievent eventb;
private hashtable<ievent, set<iobserver>> eventobservermapping;
public observable() {
this(null);
}
// 这里如果evenobservermapping传入的某些set<iobserver>是未被同步修饰的,那么也没办法
public observable(hashtable<ievent, set<iobserver>> eventobservermapping) {
if(eventobservermapping == null) {
eventobservermapping = new hashtable<ievent, set<iobserver>> ();
}
this.eventobservermapping = new hashtable<ievent, set<iobserver>> ();
this.eventa = new eventa();
this.eventb = new eventb();
}
@override
public void registerobserver(ievent event, iobserver observer) {
set<iobserver> observers = eventobservermapping.get(event);
if(observers == null) {
observers = collections.synchronizedset(new hashset<iobserver> ());
observers.add(observer);
eventobservermapping.put(event, observers);
}
else {
observers.add(observer);
}
}
@override
public void unregisterobserver(ievent event, iobserver observer) {
set<iobserver> observers = eventobservermapping.get(event);
if(observers != null) {
observers.remove(observer);
}
}
@override
public void notifyobservers(ievent event) {
set<iobserver> observers = eventobservermapping.get(event);
if(observers != null && observers.size() > 0) {
iterator<iobserver> iter = observers.iterator();
while(iter.hasnext()) {
iter.next().update(event);
}
}
}
@override
public void changestatea() {
// 改变状态a会触发事件a
eventa.eventchange();
notifyobservers(eventa);
}
@override
public void changestateb() {
// 改变状态b会触发事件b
eventb.eventchange();
notifyobservers(eventb);
}
@override
public ievent geteventa() {
return eventa;
}
@override
public ievent geteventb() {
return eventb;
}
}
interface iobserver {
void update(ievent event);
}
class observer implements iobserver {
private string name;
public observer(string name) {
this.name = name;
}
@override
public void update(ievent event) {
system.out.println(
string.format("%s receive %s's change, current observalbe's state is %s",
name, event, event.getstate()));
}
}
}
似乎看起来挺完美了,但还是不够完美。因为事件被硬编码为被观察者类的属性。这样事件类型在编译时期就被定死了,如果要增加新的事件类型就不得不修改iobservable接口和observable类,这大大削减了灵活性。
相当于被观察者耦合于这些具体的事件,那么我们如何来打破这个限制呢?
答案是引入一个新的组件,让那个组件来管理事件、观察者、被观察者之间的关系,事件发生时也由那个组件来调用观察者的回调函数。这也是一种解耦吧,有点类似spring的ioc容器。
至于具体实现,我觉得guava eventbus做得已经蛮好了,可以参考我前面提到的链接。
ps:本帖不是为guava eventbus做广告,只是自己的思路一步步推进,逐渐地就和guava eventbus的设计思路吻合了。
下面继续看看jdk标准类实现观察者模式的例子,然后分析下它的源码实现,要看的只有一个observable类和一个observer接口。
jdk标准类实现观察者模式
import java.util.observable;
import java.util.observer;
/**
* 使用java.util包中的标准类实现观察者模式
* @author will
*
*/
public class jdkobserverdemo {
public static void main(string[] args) {
jdkobserverdemo jod = new jdkobserverdemo();
// 被观察者
myobservable myobservable = jod.new myobservable("hello");
// 观察者
observer myobserver = jod.new myobserver();
// 注册
myobservable.addobserver(myobserver);
// 改变被观察者状态,触发观察者回调函数
myobservable.setvalue("will");
}
class myobservable extends observable {
private string watchedvalue; // 被观察的值
public myobservable(string watchedvalue) {
this.watchedvalue = watchedvalue;
}
public void setvalue(string newvalue) {
if(!watchedvalue.equals(newvalue)) {
watchedvalue = newvalue;
setchanged();
notifyobservers(newvalue);
}
}
@override
public string tostring() {
return "myobservable";
}
}
class myobserver implements observer {
@override
public void update(observable o, object arg) {
system.out.println(o + "'s state changed, argument is: " + arg);
}
}
}
看了下jdk标准库中的observer和observable实现很简单,不想多说了。
下面是quartz中的监听器实现。
quartzscheduler被监听者
import java.util.arraylist;
import java.util.date;
import java.util.list;
/**
* quartz核心类,相当于observable(被观察者)
* @author will
*
*/
public class quartzscheduler {
private arraylist<schedulerlistener> internalschedulerlisteners = new arraylist<schedulerlistener>(10);
// private arraylist<joblistener> interanljoblisteners = new arraylist<joblistener>(); // 一个observable可以包含多组监听器
public date schedulejob(trigger trigger) {
if(trigger == null) {
return null;
}
system.out.println("schedule job, trigger: " + trigger);
notifyschedulerlistenersscheduled(trigger);
return new date();
}
public void unschedulejob(trigger trigger) {
if(trigger == null) {
return;
}
system.out.println("unschedule job, trigger: " + trigger);
notifyshedulerlistenerunscheduled(trigger);
}
// 注册schedulerlistener
public void addinternalschedulerlistener(schedulerlistener schedulerlistener) {
synchronized (internalschedulerlisteners) {
internalschedulerlisteners.add(schedulerlistener);
}
}
// 移除schedulerlistener
public boolean removeinternalschedulerlistener(schedulerlistener schedulerlistener) {
synchronized (internalschedulerlisteners) {
return internalschedulerlisteners.remove(schedulerlistener);
}
}
public list<schedulerlistener> getinternalschedulerlisteners() {
synchronized (internalschedulerlisteners) {
return java.util.collections.unmodifiablelist(new arraylist<schedulerlistener>(internalschedulerlisteners));
}
}
public void notifyschedulerlistenersscheduled(trigger trigger) {
for(schedulerlistener listener: getinternalschedulerlisteners()) {
listener.jobscheduled(trigger);
}
}
public void notifyshedulerlistenerunscheduled(trigger trigger) {
for(schedulerlistener listener: getinternalschedulerlisteners()) {
listener.jobunscheduled(trigger);
}
}
}
schedulerlistener
// 监听接口,回调函数,client注册监听时需要提供回调函数实现
public interface schedulerlistener {
void jobscheduled(trigger trigger);
void jobunscheduled(trigger trigger);
}
trigger
// trigger
public class trigger {
private string triggerkey;
private string triggername;
public trigger(string triggerkey, string triggername) {
this.triggerkey = triggerkey;
this.triggername = triggername;
}
public string gettriggerkey() {
return triggerkey;
}
public void settriggerkey(string triggerkey) {
this.triggerkey = triggerkey;
}
public string gettriggername() {
return triggername;
}
public void settriggername(string triggername) {
this.triggername = triggername;
}
public string tostring() {
return string.format("{triggerkey: %s, triggername: %s}", triggerkey, triggername);
}
}
test
public class test {
public static void main(string[] args) {
quartzscheduler qs = new quartzscheduler();
schedulerlistener listenera = new schedulerlistener() {
@override
public void jobunscheduled(trigger trigger) {
system.out.println("listenera job unscheduled: " + trigger.gettriggername());
}
@override
public void jobscheduled(trigger trigger) {
system.out.println("listenera job scheduled: " + trigger.gettriggername());
}
};
schedulerlistener listenerb = new schedulerlistener() {
@override
public void jobunscheduled(trigger trigger) {
system.out.println("listenerb job unscheduled: " + trigger.gettriggername());
}
@override
public void jobscheduled(trigger trigger) {
system.out.println("listenerb job scheduled: " + trigger.gettriggername());
}
};
// 注册scheduler listener
qs.addinternalschedulerlistener(listenera);
qs.addinternalschedulerlistener(listenerb);
trigger triggera = new trigger("key1", "triggera");
trigger triggerb = new trigger("key2", "triggerb");
qs.schedulejob(triggera);
qs.schedulejob(triggerb);
qs.unschedulejob(triggera);
}
}