亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

java觀察者模式實現和java觀察者模式演化

2019-11-26 15:41:48
字體:
來源:轉載
供稿:網友

簡單的觀察者模式實現

復制代碼 代碼如下:

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

}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久中文字幕| 日韩精品欧美国产精品忘忧草| 日韩av免费在线播放| 精品无码久久久久久国产| 在线国产精品视频| 国产91久久婷婷一区二区| 一本一道久久a久久精品逆3p| 在线电影中文日韩| 亚洲国产精品成人一区二区| 亚洲女人天堂网| 国产精品户外野外| 国产精品久久久91| 日韩中文字幕网址| 国内精品视频一区| 91影院在线免费观看视频| 91九色综合久久| 国产亚洲精品久久久久久777| 中文字幕不卡av| 久久精品精品电影网| 国产福利成人在线| 国产成人精品优优av| 日韩成人性视频| 九九精品在线观看| 日韩av不卡在线| 欧美乱人伦中文字幕在线| 日韩精品视频在线| 久久这里有精品视频| 97婷婷涩涩精品一区| 色综合视频一区中文字幕| 欧美性生交大片免网| 欧美韩国理论所午夜片917电影| 亚洲综合中文字幕在线| 日本不卡免费高清视频| 久久亚洲一区二区三区四区五区高| 精品国内亚洲在观看18黄| 亚洲午夜精品久久久久久久久久久久| 亚洲自拍偷拍视频| 国产一区二区三区三区在线观看| 在线亚洲国产精品网| 成人激情视频免费在线| 日韩免费高清在线观看| 亚洲精品视频中文字幕| 亚洲精品美女久久久久| 亚洲国产成人久久综合| 日韩精品在线观看一区| 亚洲欧美精品中文字幕在线| 中文一区二区视频| 91在线中文字幕| 91sao在线观看国产| 中文精品99久久国产香蕉| 亚洲欧美日本伦理| 九色成人免费视频| 日韩中文娱乐网| 欧美精品在线免费播放| 伊人久久大香线蕉av一区二区| 亚洲缚视频在线观看| 色777狠狠综合秋免鲁丝| 欧美性理论片在线观看片免费| 91精品国产91久久久久久| 亚洲区中文字幕| 亚洲精品按摩视频| 欧美孕妇孕交黑巨大网站| 韩国视频理论视频久久| 国产成人精品电影| 66m—66摸成人免费视频| 国自产精品手机在线观看视频| 亚洲国产欧美在线成人app| 国产综合福利在线| 中文在线资源观看视频网站免费不卡| 国产精品影院在线观看| 中文字幕在线看视频国产欧美| 国内精品久久久久久久久| 一区二区三区国产视频| 欧美孕妇孕交黑巨大网站| 亚洲网在线观看| 亚洲福利在线视频| 亚洲乱码国产乱码精品精天堂| 不卡av电影在线观看| www.日韩视频| 亚洲福利在线视频| 91精品在线一区| 日韩性xxxx爱| 777午夜精品福利在线观看| 欧美日韩福利视频| 色偷偷av一区二区三区| 欧美专区国产专区| 成人国产精品日本在线| 久久这里有精品视频| 91精品啪在线观看麻豆免费| 久久九九全国免费精品观看| 国产精品www网站| 久久影院免费观看| 91av在线不卡| 日韩有码在线播放| 欧美成人精品不卡视频在线观看| 成人性生交xxxxx网站| 国产欧美日韩专区发布| 大荫蒂欧美视频另类xxxx| 日韩美女免费视频| 亚洲人午夜色婷婷| www.久久色.com| 中文字幕日韩在线播放| 国产精品免费看久久久香蕉| 国产精品日韩欧美综合| 国产成人福利网站| 欧美精品在线视频观看| 国产精品中文在线| 日本中文字幕久久看| 日韩在线观看网址| 亚洲iv一区二区三区| 精品免费在线视频| 精品福利免费观看| 日韩电视剧在线观看免费网站| 日韩美女在线观看一区| 一区国产精品视频| 欧美日韩性生活视频| 日本久久久久久久久| 亚洲国产欧美在线成人app| 成人网在线免费看| 日韩欧美一区二区三区久久| 日本成人免费在线| 国产91色在线| 国产在线999| 成人在线一区二区| 琪琪第一精品导航| 欧美精品一区二区免费| 91免费人成网站在线观看18| 国产精品久久久久久久久免费| 日韩av色在线| 日本一本a高清免费不卡| 91久久精品国产91久久性色| 欧美极品少妇xxxxⅹ喷水| 一道本无吗dⅴd在线播放一区| 欧美乱大交xxxxx另类电影| 69精品小视频| 国产精品久久久久久久天堂| 久久久人成影片一区二区三区| 国产精品一区二区久久精品| 北条麻妃99精品青青久久| 欧美激情综合色综合啪啪五月| 91成人精品网站| 亚洲精品欧美日韩专区| 日韩免费高清在线观看| 欧美资源在线观看| 亚洲色图av在线| 亚洲人成在线观| 久久天天躁狠狠躁老女人| 色婷婷**av毛片一区| 亚洲xxxx视频| 青青草一区二区| 欧美重口另类videos人妖| 亚洲区在线播放| 日韩亚洲欧美中文在线| 亚洲精品小视频在线观看| 欧美专区日韩视频| 久久69精品久久久久久国产越南| 国产在线拍偷自揄拍精品| 日韩成人av在线播放| 国产剧情日韩欧美| 中文字幕日韩电影| 国产精品美腿一区在线看| 久久久女人电视剧免费播放下载| 欧美三级免费观看| 中文字幕免费精品一区|