当前位置: 移动技术网 > IT编程>开发语言>Java > java观察者模式实现和java观察者模式演化

java观察者模式实现和java观察者模式演化

2019年07月22日  | 移动技术网IT编程  | 我要评论

简单的观察者模式实现

复制代码 代码如下:

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);
 }

}

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网