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

首頁 > 學院 > 開發設計 > 正文

利用Observer模式解決組件間通信問題

2019-11-18 12:15:18
字體:
來源:轉載
供稿:網友

  1. 問題的提出
  以前做一個界面的時候經常會碰到這樣的尷尬情況:希望保留各個獨立的組件(類),但又希望它們之間能夠相互通信。譬如Windows中的EXPlorer,我們希望鼠標點擊左邊是樹型目錄的一個節點,右邊的文件瀏覽能及時列出該節點目錄下的文件和子目錄,類似這樣一個簡單的應用,假如只有一個類繼續JFrame,而樹型組件和瀏覽文件的面板作為成員,就像:
  public class MainFrame extends JFrame
  {
  JPanel treePanel;
  JTree tree;
  JPanel filePanel;
  ...
  }
  
  這樣當然輕易在兩者之間傳遞消息,但是可擴展性較差。通常輕易想到的是兩種辦法:在一個組件里保留另一個組件類型的成員,初始化時作為參數傳入引用,比如:
  class TreePanel extends JPanel
  {
  JTree tree;
  ...
  }
  
  class FilePanel extends JPanel
  {
  public FilePanel(JTree tree){...}
  ...
  }
  
  
  或者將一個組件線程化,不停地監聽另一個組件的變化,然后作出相應的反映,比如:
  class TreePanel extends JPanel
  {
  JTree tree;
  ...
  }
  
  class FilePanel extends JPanel implements Runnable
  {
  public void run()
  {
  while (true)
  {
  //監聽tree的變化
  }
  ...
  }
  ...
  }
  
  這樣確實可以達到我們的目的,但是第一種方案顯然不利于松散耦合,第二種方案比較占用系統資源。通過學習設計模式,我們發現可以用Observer模式來解決這個問題。
  
  2. Observer模式
  設計模式分為創建型、結構型和行為型,其中行為型模式專門處理對象間通信,指定交互方式等,Observer模式就是屬于行為型的一種設計模式。按照“四人幫”(Gang of Four)在“Design Patterns”里的定義,Observer模式“定義對象間的一種一對多的依靠關系,當一個對象的狀態發生改變時, 所有依靠于它的對象都得到通知并被自動更新”,這個描述正好符合我們對“組件通信”問題的需求。讓我們先看看Observer模式的結構:
  
  其中各元素的含義如下:
  Subject:被觀察的目標的抽象接口,它提供對觀察者(Observer)的注冊、注銷服務,Notify方法通知Observer目標發生改變;
  Object:觀察者的抽象接口,Update方法是當得到Subject狀態變化的通知后所要采取的動作;
  ConcreteSubject:Subject的具體實現;
  ConcreteObserver:Observer的具體實現
  Observer模式在實現MVC結構時非常有用,為數據和數據表示解耦合。
  
  3. java中的Observer模式:Observer和Observable
  在大致了解了Observer模式的描述之后,現在我們更為關心的是它在Java中是如何應用的。幸運的是,自從JDK 1.0起,就有了專門處理這種應用的API,這就是Observer接口和Observable類,它們是屬于java.util包的一部分??磥鞪ava的開發者們真是深諳設計模式的精髓,而Java的確是為了真正的面向對象而生的,呵呵!
  這里的Observer和Observable分別對應設計模式中的Observer和Subject,對比一下它們定義的方法,痕跡還是相當明顯的:
  Observer的方法:
  update(Observable subject, Object arg) 監控subject,當subject對象狀態發生變化時Observer會有什么響應,arg是傳遞給Observable的notifyObservers方法的參數;
  Observable的方法:
  addObserver(Observer observer) observer向該subject注冊自己
  hasChanged() 檢查該subject狀態是否發生變化
  setChanged() 設置該subject的狀態為“已變化”
  notifyObservers() 通知observer該subject狀態發生變化
  
  4. Observer模式在Java GUI事件模型中應用
  其實在AWT/Swing事件模型中用到了好幾種設計模式,以前的JDK 1.0 AWT使用的是“基于繼續的事件模型”,在該模型Component類中定義了一系列事件處理方法,如:handleEvent,mouseDown,mouseUp等等,我們對事件的響應是通過對組件類繼續并覆蓋相應的事件處理方法的手段來實現,這種模型有很多缺點,事件的處理不應當由事件產生者負責,而且根據“設計模式”一書中的原則,“繼續”通常被認為是“對封裝性的破壞”,父子類之間的緊密耦合關系降低了靈活性,同時繼續輕易導致家族樹規模的龐大,這些都不利于組件可重用。
  JDK 1.1以后新的事件模型是被成為“基于授權的事件模型”,也就是我們現在所熟悉的Listener模型,事件的處理不再由產生事件的對象負責,而由Listener負責。尤其在Swing組件中設計MVC結構時用到了Observer模式,眾所周知,MVC表示“模型-視圖-控制器”,即“數據-表示邏輯-操作”,其中數據可以對應多種表示,這樣視圖就處在了observer的地位,而model則是subject。
  
  5. 簡單的例子
  回到本文一開始的那個Explorer的例子,我們考慮做一個簡單的圖片瀏覽器,使樹型選擇組件和圖片瀏覽面板在兩個不同的類中,其中圖片瀏覽面板根據所選擇的樹的節點顯示相應的圖片,所以圖片瀏覽面板是一個observer,樹是subject。由于Java單根繼續的原因,我們不能同時繼續JPanel和Observable,但可以用對象的組合把一個subject放到我們的類當中,并通過TreeSelectionListener觸發subject的setChanged方法,并通過notifyObservers方法通知observer。
  例子代碼如下:
  //LeFTPanel.java
  package com.jungleford.test;
  import java.awt.BorderLayout;
  import javax.swing.*;
  import javax.swing.event.TreeSelectionListener;
  import javax.swing.event.TreeSelectionEvent;
  import javax.swing.tree.DefaultMutableTreeNode;
  import java.util.Observable;
  import java.util.Observer;
  
  public final class LeftPanel extends JPanel
  {// 把樹型選擇視圖布局在左邊
  PRivate JTree tree;// 樹型選擇視圖
  private JScrollPane scroll;// 讓視圖可滾動
  private DefaultMutableTreeNode root, node1, node2;// 根節點及兩個葉子
  private Sensor sensor;// sensor是一個Observable,由于只能單根繼續,所以作為組合成員
  private String file;// 圖片文件名,與RightPanel通信的內容
  
  public LeftPanel(Observer observer)
  {
  file = "";
  sensor = new Sensor();
  sensor.addObserver(observer);// 向Observable注冊Observer
  root = new DefaultMutableTreeNode("Images");
  tree = new JTree(root);
  node1 = new DefaultMutableTreeNode("Rabbit");
  node2 = new DefaultMutableTreeNode("Devastator");
  root.add(node1);
  root.add(node2);
  tree.addTreeSelectionListener(new TreeSelectionListener()
  {// 樹節點選擇動作
  public void valueChanged(TreeSelectionEvent e)
  {
  Object obj = e.getPath().getLastPathComponent();
  if (obj instanceof DefaultMutableTreeNode)
  {
  DefaultMutableTreeNode node = (DefaultMutableTreeNode)obj;
  if (node == root)
  file = "";// 選擇根
  if (node == node1)
  file = "rabbit.jpg";// 選擇node1
  if (node == node2)
  file = "devastator.gif";// 選擇node2
  sensor.setData(file);// 改變Observable
  sensor.notifyObservers();// 通知observer,對象已改變
  }
  }
  });
  scroll = new JScrollPane(tree);
  add(scroll, BorderLayout.CENTER);
  }
  
  public Observable getSensor()
  {// 返回Observable對象,使Observer可以獲取
  return sensor;
  }
  }
  
  class Sensor extends Observable
  {// 定義自己的Observable
  private Object data;
  
  public void setData(Object newData)
  {
  data = newData;
  setChanged();// 改變Observable
  System.out.println("Data changed!");
  }
  
  public Object getData()
  {
  return data;
  }
  }
  
  //RightPanel.java
  package com.jungleford.test;
  import java.awt.*;
  import javax.swing.JPanel;
  import java.util.Observer;
  import java.util.Observable;
  
  public class RightPanel extends JPanel implements Observer
  {// 把圖片瀏覽視圖布局在右邊
  private Image image;
  
  public void update(Observable subject, Object obj)
  {// 定義接收到Observable變化后的響應動作
  String file = (String)((Sensor)subject).getData();
  if (!file.equals(""))
  {
  image = Toolkit.getDefaultToolkit().getImage(file);
  MediaTracker tracker = new MediaTracker(this);// 定義圖像跟蹤
  tracker.addImage(image, 0);
  try
  {
  tracker.waitForID(0);// 等待圖像的完全加載
  }
  catch (InterruptedException e)
  {
  e.printStackTrace();
  }
  }
  else
  image = null;
  repaint();// 重繪組件
  }
  
  public void paintComponent(Graphic

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩成人免费| 97热在线精品视频在线观看| 国产极品jizzhd欧美| 亚洲va欧美va国产综合久久| 97在线视频国产| 欧美电影第一页| 成人xvideos免费视频| 日本一区二区三区四区视频| 欧美综合激情网| 色悠悠国产精品| 91亚洲精品久久久久久久久久久久| 精品偷拍各种wc美女嘘嘘| 久久久免费电影| 欧美大片在线看| 久久久久久久久久亚洲| 永久免费毛片在线播放不卡| 国产专区欧美专区| 最近中文字幕日韩精品| 精品中文字幕在线观看| 亚洲精品资源在线| 国产成人精品综合久久久| 日本久久久久久久久久久| 欧美国产日韩一区二区在线观看| 亚洲最新在线视频| 91高清视频免费观看| 国产精品高潮在线| 久久99国产综合精品女同| 久久精品亚洲一区| 精品久久久久人成| 国产性猛交xxxx免费看久久| 国产精品成人观看视频国产奇米| 欧美黑人国产人伦爽爽爽| 国产精品女人久久久久久| 日韩精品免费视频| 性亚洲最疯狂xxxx高清| 欧美激情综合亚洲一二区| 久久久精品美女| 国产亚洲精品激情久久| 国产精品成人va在线观看| 欧美精品一区三区| 日韩精品免费综合视频在线播放| 一个人看的www久久| 欧美亚洲视频一区二区| 欧美精品一区三区| 啪一啪鲁一鲁2019在线视频| 国产精品久久久久久亚洲调教| 91精品视频一区| 欧美精品18videos性欧美| 国产精品永久免费观看| 日韩电影免费观看中文字幕| 欧美在线视频在线播放完整版免费观看| www.欧美精品一二三区| 成人在线一区二区| 亚洲成人精品av| 日韩视频中文字幕| 亚洲午夜精品视频| 91性高湖久久久久久久久_久久99| 亚洲精品mp4| 68精品国产免费久久久久久婷婷| 欧美裸体xxxx极品少妇软件| 欧美肥婆姓交大片| 亚洲一区二区三区视频播放| 中文字幕日韩精品在线观看| 国产欧美日韩丝袜精品一区| 日韩在线免费观看视频| 日韩精品中文字幕有码专区| 亚洲xxxx做受欧美| 国产精品亚洲综合天堂夜夜| 91欧美精品午夜性色福利在线| 国产精品777| 欧美综合国产精品久久丁香| 国产成人精品视| 中文字幕日韩精品在线| 45www国产精品网站| 欧美伊久线香蕉线新在线| 亚洲性无码av在线| 在线日韩精品视频| 91精品视频专区| 97视频在线观看免费高清完整版在线观看| 亚洲综合色av| 欧美日韩精品在线观看| 国产精品第一第二| 91色在线观看| 国产欧美久久久久久| 亚洲午夜久久久久久久| 亚洲一区www| 国产精品高潮呻吟久久av黑人| 亚洲天堂男人的天堂| 国产91精品久久久| 国产精品video| 91精品久久久久| 中文字幕日韩免费视频| 国产精品久久国产精品99gif| 亚洲激情中文字幕| 亚洲福利在线看| 国产一区二区三区在线观看视频| 欧美电影免费观看大全| 日本91av在线播放| 日韩成人激情影院| 最新国产精品拍自在线播放| 欧美与欧洲交xxxx免费观看| 国产精品久久久久久久久男| 国产suv精品一区二区| 国产97在线视频| xx视频.9999.com| 亚洲人成人99网站| 国产精品美女久久久久久免费| 亚洲网在线观看| 欧美日韩人人澡狠狠躁视频| 亚洲自拍偷拍福利| 国产精品免费电影| 国产精品∨欧美精品v日韩精品| 日韩中文字幕在线免费观看| 日韩高清中文字幕| 欧美极品美女视频网站在线观看免费| x99av成人免费| 欧美午夜精品伦理| 日本精品免费观看| 国产亚洲一级高清| 久久精品小视频| 这里只有精品久久| 韩剧1988免费观看全集| 热99在线视频| 少妇久久久久久| yw.139尤物在线精品视频| 亚洲字幕在线观看| 亚洲人成电影网站色www| 在线精品播放av| 欧美日韩一区二区三区在线免费观看| 国产精品丝袜久久久久久不卡| 欧美精品免费在线观看| 亚洲免费高清视频| 中文字幕欧美日韩va免费视频| 久久久久久久久久亚洲| 欧美亚洲国产视频| 一区二区三区 在线观看视| 国产精品69久久久久| 国产精品久久久久久久av大片| 亚洲精品久久久久久下一站| 亚洲一区中文字幕在线观看| 久久深夜福利免费观看| 亚洲色图校园春色| 菠萝蜜影院一区二区免费| 色婷婷综合成人av| 最近免费中文字幕视频2019| 午夜精品免费视频| 日韩中文字幕在线| 欧美激情伊人电影| 国产精品男女猛烈高潮激情| 精品无人国产偷自产在线| 97色在线观看| 欧美日韩午夜视频在线观看| 亚洲女人天堂成人av在线| 欧美成人免费全部| 主播福利视频一区| 国产精品视频永久免费播放| 国产一区二区成人| 国产国语videosex另类| 福利一区视频在线观看| 久久精品视频网站| 欧美一区二区三区四区在线| 欧美性猛xxx| 欧美成aaa人片免费看| 精品免费在线视频|