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

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

觀察者模式組圖(Observer Pattern)

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

  描述:
  
  在設計一組依靠的對象與它們所依靠的對象之間一致(同步)的交流模型時,觀察者模式(Observer Pattern)很有用。它可以使依靠對象的狀態與它們所依靠的對象的狀態保持同步。這組依靠的對象指的是觀察者(Observer),它們所依靠的對象稱為主題(Subject)。為了實現觀察者(Observer)的狀態與主題(Subject)保持同步,觀察者模式(Observer Pattern)
  
  推薦采用發布者--訂閱者(publisher--subscriber)模型,以使這組觀察者(Observer)和主題(Subject)對象之間有清楚的界限。
  
  典型的觀察者(Observer)是一個依靠于或者關注于主題對象的狀態的對象。一個主題可以有一個或者多個觀察者。這些觀察者在主體的狀態發生變化時,需要得到通知。
  
  由于給定主體的觀察者鏈表需要動態的變化,因此一個主題不能維護一個靜態的觀察者鏈表。因此關注于主題狀態的任何對象都需要明確地注冊自己為主體的一個觀察者。主題狀態發生的變化,都需要通知所有的以注冊的觀察者。從主題接到通知以后,每一個觀察者查詢主題,使自己的狀態與主題的同步。因此一個主題扮演著發布者的角色,發布信息到所有的以訂閱的觀察者。
  
  換句話說,主題和它的觀察者之間包含了一對多的關系。當主題的實例的狀態發生變化時,所有的依靠于它的觀察者都會得到通知并更新自己。每一個觀察者對象需要向主題注冊,當主題的狀態發生變化的時候得到通知。一個觀察者可以注冊或者訂閱多個主題。當觀察者不希望再得到通知時,它可以向主題進行注銷。
  
  為了實現這種機制:
  
  (1)  主題需要為注冊和注銷通知提供一個接口。
  
 ?。?)  下面的兩點也需要滿足:
  
  A、  拉模型(In the pull model)--主題需要提供一個接口,可以使觀察者查詢主題獲得需要的狀態信息來更新自己的狀態。
  
  B、  推模型(In the push model)--主題發送觀察者可能關注的狀態信息。
  
  (3)  觀察者需要提供一個可以從主題接受通知的接口。
  
  類圖(圖33.1)描述了為滿足于以上需求,不同類的結構和它們之間的關聯關系。
  
 觀察者模式組圖(Observer Pattern)(圖一)
  Figure 33.1: Generic Class Association When the Observer Pattern Is Applied
  

  從這個類圖可以看到:
  
 ?。?)  所有的主題需要提供一個類似于Observable接口的實現。
  
 ?。?)  所有的觀察者需要提供一個類似于Observer接口的實現。
  
  在應用觀察者模式時,有幾種變體。這就會產生不同類型的主題--觀察者模式,例如,觀察者僅關注主體特定類型的變化等。
  
  增加新的觀察者:
  
  應用觀察者模式以后,在不影響主題類的情況下,可以動態的加入不同的觀察者。同樣,主題的狀態變化邏輯改變時,觀察者也不會受到影響。
  
  例子:
  
  為了治理一個賣廠多個分類產品,讓我們建立一個銷售報表系統。這個系統有以下特征:
  
 ?。?)  用戶可以選擇一個他們感愛好的分類
  
 ?。?)  在選擇了一個分類以后,需要顯示下面的兩種類型的報表。
  
  A、  月度報表(Monthly report)--所選分類當月的所有交易清單。
  
  B、  年度累積額(YTD sales chart)--以月為單位顯示選擇分類的年度累積額圖。
  
 ?。?)  當一個不同的分類被選擇時,兩種報表的數據會被刷新,顯示當前所選分類的報表。
  
  為了實現以上期望的功能,我們很輕易的看到兩個報表對象依靠于持有用戶選擇分類的對象。應用觀察者模式于此場景,我們可以設計一個介于持有用戶選擇分類的對象和兩個報表對象之間一個一致(同步)的交流模型。
  
  讓我們定義三個類,它們的功能如表33.1所描述:
  
  Table 33.1: Subject-Observer Classes
  public interface Observable {
  public void notifyObservers();
  public void register(Observer obs);
  public void unRegister(Observer obs);
  }
  
  ReportManager類(Listing33.1)提供了聲明在Observable接口中方法的實現。兩個依靠于ReportManager的報表對象使用這些方法注冊它們自己為觀察者。ReportManager把這些注冊的觀察者保存到observersList矢量(vector)中。當前選擇的分類構成了ReportManager對象的狀態,它以實例變量的形式保存在變量department中。當為department設置一個新的值時(也就是ReportManager對象的狀態改變),notifyObservers方法被調用。作為notifyObservers方法的一部分,ReportManager調用注冊為觀察者的refreshData(Observable)方法。
  Listing 33.1: ReportManager Class
  
  public class ReportManager extends JFrame
  implements Observable {
  …
  …
  PRivate Vector observersList;
  private String department;
  public ReportManager() throws Exception {
  …
  …
  observersList = new Vector();
  …
  …
  }
  public void register(Observer obs) {
  //Add to the list of Observers
  observersList.addElement(obs);
  }
  public void unRegister(Observer obs) {
  //remove from the list of Observers
  }
  public void notifyObservers() {
  //Send notify to all Observers
  for (int i = 0; i < observersList.size(); i++) {
  Observer observer =
  (Observer) observersList.elementAt(i);
  observer.refreshData(this);
  }
  }
  public String getDepartment() {
  return department;
  }
  public void setDepartment(String dept) {
  department = dept;
  }
  class ButtonHandler implements ActionListener {
  ReportManager subject;
  public void actionPerformed(ActionEvent e) {
  if (e.getActionCommand().equals(ReportManager.EXIT)) {
  System.exit(1);
  }
  if (e.getActionCommand().equals(ReportManager.SET_OK)) {
  String dept = (String)
  cmbDepartmentList.getSelectedItem();
  //change in state
  subject.setDepartment(dept);
  subject.notifyObservers();
  }
  }
  public ButtonHandler() {
  }
  public ButtonHandler(ReportManager manager) {
  subject = manager;
  }
  }
  }//end of class
  
  除了提供Observable接口方法的實現,ReportManager還顯示了必要的用戶接口,答應用戶選擇一個特定的、關注的分類。
  
  讓我們定義接口Observer的兩個實現:MonthlyReport和YTDChart類
  
  public interface Observer {
  public void refreshData(Observable subject);
  }
  
 觀察者模式組圖(Observer Pattern)(圖二)
  Figure 33.2: Observer Class Hierarchy
  

  Listing 33.2: MonthlyReport Class as an Observer
  
  public class MonthlyReport extends JFrame implements Observer {
  …
  …
  private ReportManager objReportManager;
  public MonthlyReport(ReportManager inp_objReportManager)
  throws Exception {
  super("Observer Pattern -- Example");
  objReportManager = inp_objReportManager;
  //Create controls
  …
  …
  //Create Labels
  …
  …
  objReportManager.register(this);
  }
  public void refreshData(Observable subject) {
  if (subject == objReportManager) {
  //get subject's state
  String department = objReportManager.getDepartment();
  lblTransactions.setText(
  "Current Month Transactions - " +
  department);
  Vector trnList =
  getCurrentMonthTransactions(department);
  String content = "";
  for (int i = 0; i < trnList.size(); i++) {
  content = content +
  trnList.elementAt(i).toString() + "/n";
  }
  taTransactions.setText(content);
  }
  }
  private Vector getCurrentMonthTransactions(String department
  ) {
  Vector v = new Vector();
  FileUtil futil = new FileUtil();
  Vector allRows = futil.fileToVector("Transactions.date");
  //current month
  Calendar cal = Calendar.getInstance();
  cal.setTime(new Date());
  int month = cal.get(Calendar.MONTH) + 1;
  String searchStr = department + "," + month + ",";
  int j = 1;
  for (int i = 0; i < allRows.size(); i++) {
  String str = (String) allRows.elementAt(i);
  if (str.indexOf(searchStr) > ?1) {
  StringTokenizer st =
  new StringTokenizer(str, ",");
  st.nextToken();//bypass the department
  str = " " + j + ". " + st.nextToken() + "/" +
  st.nextToken() + "~~~" +
  st.nextToken() + "Items" + "~~~" +
  st.nextToken() + " Dollars";
  j++;
  v.addElement(str);
  }
  }
  return v;
  }
  }//end of class
  
  ReportManager利用這個接口通知它的所有觀察者。
  
  主題--觀察者的關聯(Subject--Observer Association)
  
  通常,一個客戶首先需要創建一個主題(ReportManager)實例,當一個觀察者(例如:MonthlyReport,YTDChart)對象被創建。客戶把主題ReportManager實例的引用傳遞給觀察者的構造函數,觀察者將自身注冊到當前主題實例上。
  
  //Client Code
  public class SupervisorView {
  …
  …
  public static void main(String[] args) throws Exception {
  //Create the Subject
  ReportManager objSubject = new ReportManager();
  //Create Observers
  new MonthlyReport(objSubject);
  new YTDChart(objSubject);
  }
  }//end of class
  
  類之間的關聯描述如下:
  
 觀察者模式組圖(Observer Pattern)(圖三)
  Figure 33.3: Example application--Class Association
  

  邏輯流程:
  
  (1)  使用ReportManager用戶接口,當用戶選擇一個特定的分類并且點擊OK按鈕時,ReportManager的內部狀態被被改變(例如,ReportManager實例變量department的值發生改變)。
  
  (2)  新的狀態一旦被設置,ReportManager調用兩個注冊的觀察者MonthlyReport和YTDChart的refreshData(Observable)方法。
  
 ?。?)  作為refreshData方法的一部分,兩個report對象需要:
  
  A、  檢查以確保調用refreshData方法的主題和觀察者這冊的主題是同一個主題。這就避免了觀察者響應不必要的調用。
  
  B、  使用getDepartment方法查詢ReportManager的當前狀態。
  
  C、  從數據文件中提取響應的數據顯示。
  
 觀察者模式組圖(Observer Pattern)(圖四)
  Figure 33.4: MonthlyReport View

  
  當ReportManager的狀態變化邏輯實現需要改變時,任何觀察者不受影響。同樣,當一個新的觀察者被加入時,ReportManager類不需要任何變化。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩电影中文 亚洲精品乱码| 久久久亚洲欧洲日产国码aⅴ| 久久国产精品亚洲| 国语自产精品视频在线看| 久久久伊人日本| 亚洲色图狂野欧美| 91久久精品国产91性色| 亚洲国产精品999| 欧美另类精品xxxx孕妇| 97在线观看免费| 欧美激情一区二区三区久久久| 国产美女精品视频| 日韩av电影在线播放| 成人精品在线观看| 伊人伊人伊人久久| 最近2019中文字幕一页二页| 亚洲字幕一区二区| 国产精品女主播视频| 中文综合在线观看| 日本午夜人人精品| 尤物yw午夜国产精品视频| 欧美巨猛xxxx猛交黑人97人| 国产视频精品自拍| 2019亚洲日韩新视频| 日韩在线精品一区| 日韩在线视频免费观看高清中文| 亚洲乱码av中文一区二区| 欧洲亚洲在线视频| 插插插亚洲综合网| 日韩欧美在线免费观看| 中文字幕欧美专区| 日韩国产欧美精品一区二区三区| 国产亚洲人成网站在线观看| 日韩女优人人人人射在线视频| 91精品国产精品| 久热在线中文字幕色999舞| 日韩免费高清在线观看| 在线不卡国产精品| 91精品美女在线| 亚洲国产精品字幕| 精品调教chinesegay| 久久全球大尺度高清视频| 国产精品第七十二页| 亚洲已满18点击进入在线看片| 国产精品99久久久久久久久久久久| 欧美一区二区.| 亚洲精品少妇网址| 亚洲成人av片在线观看| 久久亚洲国产成人| 日日狠狠久久偷偷四色综合免费| 欧美激情亚洲精品| 久久99久国产精品黄毛片入口| 91在线视频一区| 久久精品91久久久久久再现| 欧美一级视频在线观看| 国产成人精品999| 亚洲欧美国产日韩中文字幕| 成人黄色网免费| 亚洲精品一二区| 久久在线精品视频| 国产精品视频在线观看| 精品成人乱色一区二区| 色播久久人人爽人人爽人人片视av| 欧美激情一区二区三级高清视频| 国自产精品手机在线观看视频| 国外日韩电影在线观看| 成人免费福利在线| 欧美黑人又粗大| 日韩精品在线播放| 国产亚洲精品美女久久久久| 青青草原成人在线视频| 国产一区二区三区久久精品| 一区二区在线免费视频| 日韩精品在线观看一区| 亚洲精品一区av在线播放| 亚洲一区二区精品| 国产成人综合精品在线| 久久男人av资源网站| 亚洲第一视频在线观看| 亚洲最大在线视频| 国产自产女人91一区在线观看| 热99精品里视频精品| 不卡av在线播放| 亚洲国产精品久久久久秋霞蜜臀| 国产专区欧美专区| 久久99视频精品| 97国产真实伦对白精彩视频8| 日韩精品在线观| 精品国产91久久久久久老师| 欧美一区二区三区免费观看| 国产免费成人av| 最近更新的2019中文字幕| 精品久久久久久久久久久| 69**夜色精品国产69乱| 日韩av资源在线播放| 亚洲欧美三级在线| 精品一区二区电影| 性亚洲最疯狂xxxx高清| 最近2019年日本中文免费字幕| 色无极影院亚洲| 欧美一区二粉嫩精品国产一线天| 国外视频精品毛片| 精品国产乱码久久久久久天美| 成人日韩av在线| 亚洲欧美一区二区精品久久久| 成人性生交大片免费观看嘿嘿视频| 欧美日韩中文字幕综合视频| 亚洲欧洲国产精品| 91九色在线视频| 久热精品视频在线免费观看| 欧美日韩亚洲视频| 日韩亚洲综合在线| 一夜七次郎国产精品亚洲| 国产精品久久久久久久天堂| 国产精品激情av电影在线观看| 久久久噜噜噜久噜久久| 国产精品久久久av久久久| 6080yy精品一区二区三区| 亚洲第一福利视频| 亚洲久久久久久久久久久| 亚洲国产精品小视频| 国产精品a久久久久久| 日韩成人av在线| 黑人巨大精品欧美一区免费视频| 亚洲人成人99网站| 亚洲专区国产精品| 国产精品久久久久久久9999| 亚洲欧美中文另类| 国产精品亚洲欧美导航| 国产精品天天狠天天看| 97在线视频观看| 97香蕉超级碰碰久久免费软件| 在线观看日韩av| 伦理中文字幕亚洲| 2019中文在线观看| 亚洲免费电影在线观看| 亚洲日本欧美中文幕| 亚洲第一av在线| 中文字幕亚洲无线码a| 欧美成人精品h版在线观看| 国产免费一区二区三区在线观看| 高清欧美电影在线| 久久久精品久久| 国产精品久久久久久久av电影| 欧美电影在线观看| 国产精品直播网红| 亚洲一区精品电影| 久久中文字幕在线视频| 91色中文字幕| 日韩中文在线中文网在线观看| 久久视频这里只有精品| 亚洲激情第一页| 一区二区三区回区在观看免费视频| 91久久久国产精品| 九九九久久久久久| 欧美成人在线影院| 欧美大片大片在线播放| 中文字幕日韩有码| 欧美成人精品在线观看| 日韩av电影国产| 国产精品久久久久久久久影视| 久久久之久亚州精品露出| 久久久这里只有精品视频| 国产精品女主播视频|