最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java觀察者模式實現(xiàn)和java觀察者模式演化

 更新時間:2014年02月18日 09:57:11   作者:  
觀察者模式是經(jīng)典設(shè)計模式中很常用的一種,平常我們看到的監(jiān)聽器,基本上都是采用這種設(shè)計模式實現(xiàn)的,這里探討一下觀察者模式的演化

簡單的觀察者模式實現(xiàn)

復(fù)制代碼 代碼如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * 觀察者模式中用到了回調(diào):
 * A. 觀察者將自己注冊到被觀察者的監(jiān)聽者列表,且觀察者類自身提供了一個回調(diào)函數(shù)
 * B. 被觀察者(Observable或Subject)維護(hù)觀察者列表,并且可以注冊和解注冊觀察者
 * C. 一旦被觀察者狀態(tài)發(fā)生改變,它可以調(diào)用notifyObservers(),這個方法將遍歷觀察者列表并逐個調(diào)用
觀察者提供的回調(diào)函數(shù)
 * @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()));
  }

 }

}

上面的實現(xiàn)直接將被觀察者對象作為回調(diào)函數(shù)參數(shù),這樣做很不優(yōu)雅,在簡單的場景可能奏效。
但事實上更多情況下,一個被觀察者有很多種事件或者狀態(tài),而每個觀察者可能感興趣的事件或狀態(tài)都不相同,或者為了信息隱藏的目的,不想讓每個觀察者都能訪問到Observable內(nèi)部的所有狀態(tài)。
這樣我繼續(xù)演化代碼為下面這個版本,注意我這里沒有很細(xì)致地考慮并發(fā)問題。

復(fù)制代碼 代碼如下:

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

  // 改變被觀察者狀態(tài)
  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);
  // 通知觀察者某個事件發(fā)生了
  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() {
   // 改變狀態(tài)A會觸發(fā)事件A
   eventA.eventChange();
   notifyObservers(eventA);
  }

  @Override
  public void changeStateB() {
   // 改變狀態(tài)B會觸發(fā)事件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類,這大大削減了靈活性。
相當(dāng)于被觀察者耦合于這些具體的事件,那么我們?nèi)绾蝸泶蚱七@個限制呢?
答案是引入一個新的組件,讓那個組件來管理事件、觀察者、被觀察者之間的關(guān)系,事件發(fā)生時也由那個組件來調(diào)用觀察者的回調(diào)函數(shù)。這也是一種解耦吧,有點類似Spring的IOC容器。
至于具體實現(xiàn),我覺得Guava EventBus做得已經(jīng)蠻好了,可以參考我前面提到的鏈接。

PS:本帖不是為Guava EventBus做廣告,只是自己的思路一步步推進(jìn),逐漸地就和Guava EventBus的設(shè)計思路吻合了。

下面繼續(xù)看看JDK標(biāo)準(zhǔn)類實現(xiàn)觀察者模式的例子,然后分析下它的源碼實現(xiàn),要看的只有一個Observable類和一個Observer接口。

JDK標(biāo)準(zhǔn)類實現(xiàn)觀察者模式

復(fù)制代碼 代碼如下:

import java.util.Observable;
import java.util.Observer;

/**
 * 使用java.util包中的標(biāo)準(zhǔn)類實現(xiàn)觀察者模式
 * @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);
  // 改變被觀察者狀態(tài),觸發(fā)觀察者回調(diào)函數(shù)
  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標(biāo)準(zhǔn)庫中的Observer和Observable實現(xiàn)很簡單,不想多說了。
下面是Quartz中的監(jiān)聽器實現(xiàn)。

QuartzScheduler被監(jiān)聽者

復(fù)制代碼 代碼如下:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Quartz核心類,相當(dāng)于Observable(被觀察者)
 * @author will
 *
 */
public class QuartzScheduler {

 private ArrayList<SchedulerListener> internalSchedulerListeners = new ArrayList<SchedulerListener>(10);
// private ArrayList<JobListener> interanlJobListeners = new ArrayList<JobListener>();   // 一個Observable可以包含多組監(jiān)聽器

 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

復(fù)制代碼 代碼如下:

// 監(jiān)聽接口,回調(diào)函數(shù),Client注冊監(jiān)聽時需要提供回調(diào)函數(shù)實現(xiàn)
public interface SchedulerListener {

 void jobScheduled(Trigger trigger);

 void jobUnScheduled(Trigger trigger);

}

Trigger

復(fù)制代碼 代碼如下:

// 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

復(fù)制代碼 代碼如下:

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

}

相關(guān)文章

  • Java中的abstract和interface

    Java中的abstract和interface

    abstract和interface關(guān)鍵字在Java中隨處可見,它是Java三大特性封裝、繼承、多態(tài)特性的實現(xiàn)重要支柱之一。interface關(guān)鍵字用于定義接口抽象,其本質(zhì)上是用于定義類型、定義類所具有的能力,下面來看看詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • Java中System.setProperty()用法與實際應(yīng)用場景

    Java中System.setProperty()用法與實際應(yīng)用場景

    System.setProperty是Java中用于設(shè)置系統(tǒng)屬性的方法,它允許我們在運行時為Java虛擬機(jī)(JVM)或應(yīng)用程序設(shè)置一些全局的系統(tǒng)屬性,下面這篇文章主要給大家介紹了關(guān)于Java中System.setProperty()用法與實際應(yīng)用場景的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • Intellij?IDEA創(chuàng)建web項目的超詳細(xì)步驟記錄

    Intellij?IDEA創(chuàng)建web項目的超詳細(xì)步驟記錄

    如果剛開始接觸IDEA,或者之前使用的是eclipse/myEclipse的話,即使是創(chuàng)建一個JAVA WEB項目,估計也讓很多人費了好幾個小時,下面這篇文章主要給大家介紹了關(guān)于Intellij?IDEA創(chuàng)建web項目的超詳細(xì)步驟,需要的朋友可以參考下
    2022-08-08
  • 在Spring框架下配置Quartz集群的詳細(xì)步驟(MySQL數(shù)據(jù)源)

    在Spring框架下配置Quartz集群的詳細(xì)步驟(MySQL數(shù)據(jù)源)

    Quartz 是一個功能強(qiáng)大的調(diào)度庫,可以在 Java 應(yīng)用中用于執(zhí)行定時任務(wù),本文將介紹如何在 Spring 框架下配置 Quartz 集群,并使用 MySQL 作為數(shù)據(jù)源來存儲調(diào)度信息,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2025-01-01
  • springboot中swagger、異步/定時/郵件任務(wù)的問題

    springboot中swagger、異步/定時/郵件任務(wù)的問題

    這篇文章主要介紹了springboot中swagger、異步/定時/郵件任務(wù)的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • JAVA多線程實現(xiàn)的四種方式及使用場景詳解

    JAVA多線程實現(xiàn)的四種方式及使用場景詳解

    這篇文章主要介紹了JAVA多線程實現(xiàn)的四種方式及使用場景,并舉例說明了在管理系統(tǒng)中多線程的應(yīng)用場景,如數(shù)據(jù)導(dǎo)入導(dǎo)出、數(shù)據(jù)緩存更新、并發(fā)用戶操作處理、系統(tǒng)監(jiān)控和定時任務(wù)執(zhí)行,需要的朋友可以參考下
    2025-01-01
  • mybatis中的count()按條件查詢方式

    mybatis中的count()按條件查詢方式

    這篇文章主要介紹了mybatis中的count()按條件查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 使用Spark?SQL實現(xiàn)讀取不帶表頭的txt文件

    使用Spark?SQL實現(xiàn)讀取不帶表頭的txt文件

    這篇文章主要為大家詳細(xì)介紹了如何使用Spark?SQL實現(xiàn)讀取不帶表頭的txt文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Junit單元測試框架架包的導(dǎo)入全過程

    Junit單元測試框架架包的導(dǎo)入全過程

    這篇文章主要介紹了Junit單元測試框架架包的導(dǎo)入全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • SpringBoot集成swagger的實例代碼

    SpringBoot集成swagger的實例代碼

    Swagger 是一款RESTFUL接口的文檔在線自動生成+功能測試功能軟件,這篇文章主要介紹了SpringBoot集成swagger,需要的朋友可以參考下
    2017-12-12

最新評論

额济纳旗| 巨鹿县| 龙山县| 海盐县| 紫金县| 太原市| 出国| 镇坪县| 木兰县| 白城市| 西峡县| 正安县| 张家界市| 交口县| 北京市| 津南区| 沐川县| 黄山市| 临城县| 蒲江县| 天台县| 镇巴县| 永泰县| 华宁县| 克东县| 余庆县| 原平市| 灵山县| 寿光市| 日喀则市| 万载县| 仁布县| 巫山县| 乌审旗| 汝城县| 嘉祥县| 绍兴市| 沙坪坝区| 汾阳市| 兴化市| 孝昌县|