2010年7月31日 星期六

[OO 設計模式] Observer Pattern : 觀察者模式

前言 :
在 Head-First Design Pattern 第二章接著介紹 Observer Pattern, 首先我們來看看它是怎麼介紹這個Pattern :
Don't miss out when something interesting happens! We've got a pattern that keeps your objects in the know when something they might care about happens. Objects can even decide at runtime whether they want to be kept informed. The Observer Pattern is one of the most heavily used patterns in the JDK, and it's incredibly useful. Before we're done, we'll also look at one to many relationships and loose coupling. With Observer, you'll be the life of Patterns Party.

另外這裡也有提出一些設計原則 :
* Design Principe
- Strive for loosely coupled designs between objects that interact.


Observer Pattern 定義 :
The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

UML 示意圖 :


範例說明 :
在書中, 作者舉了一個氣象局RSS 的例子, 考慮以有一個WeatherData 物件可以提供相關氣象訊息, 並且它提供一支API:measurementsChanged 當氣象數據變更時, 這支API 就會被Callback. 而我們要作的就是當Callback 時, 則取出變化的氣象數據並顯示到Displays 上 (Display 可以是多個). 粗略示意圖如下 :

為了能夠動態增加Display devices 而在遵守設計原則 "OCP" (對修改封閉;對擴充開放), 可以聯想到報紙訂閱的流程 :
1. You subscribe to a particular publisher, and every time there's a new edition it gets delivered to you. As long as you remain a subscriber, you get new newspapers.
2. You unsubscribe when you don't want papers anymore, and they stop being delivered.
3. While the publisher remains in business, people, hotels, airlines and other businesses constantly subscribe and unsubscribe to the newspaper.

如果你懂怎麼訂閱報紙, 那麼觀察者模式就是 :
Publishers + Subscribers = Observer Pattern
其中publisher 就是 SUBJECT, 而 subscribers 就是 OBSERVERS.

範例代碼 :
請參考下面 UML 示意圖 : (詳細代碼請參考附件)

* WeatherStation 類別代碼 :
  1. package hf.dp.ch02;  
  2.   
  3. public class WeatherStation {  
  4.     public static void main(String args[]) {  
  5.         WeatherData wd = new WeatherData(); //Create WeatherData object (Subject)  
  6.         CurrentConditionDisplay ccDisplay = new CurrentConditionDisplay(wd); //Create display element (Observer)  
  7.         wd.setMeasurement(559012); // State change.  
  8.         wd.setMeasurement(608915); // State change.  
  9.         ccDisplay.unSubscribe(); //Unsubscribe. So won't get updated from WeatherData.  
  10.         wd.setMeasurement(719217); // State change.  
  11.     }  
  12. }  

執行結果 :
Current Condition: 55.0 F degress & 90.0% humidity
Current Condition: 60.0 F degress & 89.0% humidity <第三次State Change, 因為Observer 已經Unsubscribe, 所以不會顯示>


補充說明 :
Wiki on Observer Pattern :
The observer pattern (a subset of the publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

史帝芬心得筆記 : Design Pattern - Observer
Observer的目的在於定義一對多的物件依存關係,讓物件狀態一有變動,就自動通知其他相依物件做該做的更新動作,這個Pattern可以說是MVC的基礎架構。我自己第一次使用它是用在電子郵件認證,當系統收到使用者回覆的email時,通知所有相關物件處理後續事項; 第二次使用是在電腦象棋中,當電腦決定出下一著手時,通知棋盤、棋著列表和歷史棋著儲存區更新狀態。這是個常有機會用到的Pattern,學會了一定會受益良多。在 Observer裡的update是NumberGenerator用來通知Observer,內容已被更新的method

 Filenamehf.rar[Disk]Download
 DescriptionWeatherData 範例程式
 Filesize2 Kbytes
 Downloaded: 0 time(s)

[ Java 小學堂 ] Java 世界裡 equals 與 == 的差別


轉載自 這裡
前言 :
在Java裡,equals和==常令程式設計師困惑,這裡簡單說明如下 :
1. ==
測試物件參考時,唯有當兩個參考指向同一物件時,==運算子的結果才為true,同樣的,唯有當兩個參考指向不同物件時,!=運算子的結果才為true,這兩個運算子的處理與物件的內容無關。需要特別注意的是,在String中使用==,因為Java為節省記憶體,會在某一輪調區中維護唯一的String物件,所以如果在類別裡使用同一字串,Java只會建立一個唯一的字串而已。

2. equals
另一種測試的做法是equals,equals在類別為Java原先就存在時,是比較兩個物件是否為相同類型的類別後再比較其內容值是否相同,是就傳回true,否就傳回false。當要測試的類別是自定類別時,要依自定類別所提供的equals來決定如何比較,如果自定類別沒有覆蓋Object的equals類別的話,就以Object的equals來比較,Object的equals的比較方式如同==。

範例程式 :
下面以簡單的範例程式說明 equals 與 == 的差別 :
- myObject1.java 代碼 :
  1. package test;  
  2.   
  3. public class myObject1 {  
  4.      int nNum = 100;  
  5.        
  6.       public void setNum(int nN) {  
  7.         nNum = nN;  
  8.       }  
  9.        
  10.       public int getNum() {  
  11.         return nNum;  
  12.       }  
  13.        
  14.       public void printNum() {  
  15.         System.out.println(nNum);  
  16.       }  
  17. }  
- myObject2.java 代碼 :
  1. package test;  
  2.   
  3. public class myObject2 {  
  4.      int nNum = 100;  
  5.        
  6.       public void setNum(int nN) {  
  7.         nNum = nN;  
  8.       }  
  9.        
  10.       public int getNum() {  
  11.         return nNum;  
  12.       }  
  13.        
  14.       public void printNum() {  
  15.         System.out.println(nNum);  
  16.       }  
  17.        
  18.       public boolean equals(Object obj) {  
  19.         if (obj == nullreturn false;  
  20.         if (!(obj instanceof myObject2)) return false;  
  21.         return this.nNum == ((myObject2) obj).getNum();  
  22.       }  
  23. }  
- myEquals.java 代碼 :
  1. package test;  
  2.   
  3. public class myEquals {  
  4.   
  5.     public myEquals() {  
  6.         //字串型別  
  7.         String sA = "ABC";  
  8.         String sB = "ABC";  
  9.         String sC = new String("ABC");  
  10.        
  11.           //==的比較  
  12.         if (sA == sB)  
  13.           System.out.println("sA == sB (Because of String pool)");  
  14.         else  
  15.           System.out.println("sA != sB");  
  16.        
  17.         if (sA == sC)  
  18.           System.out.println("sA == sC");  
  19.         else  
  20.           System.out.println("sA != sC (Because sC uses new operator)");  
  21.        
  22.           //equals的比較  
  23.         if (sA.equals(sB))  
  24.           System.out.println("sA.equals(sB) = true (Because of the same value)");  
  25.         else  
  26.           System.out.println("sA.equals(sB) = false");  
  27.        
  28.         if (sA.equals(sC))  
  29.           System.out.println("sA.equals(sC) = true (Because of the same value)");  
  30.         else  
  31.           System.out.println("sA.equals(sC) = false");  
  32.        
  33.         //Java原有的型別  
  34.         Long lngA = new Long(100);  
  35.         Long lngB = new Long(100);  
  36.         Long lngC = new Long("100");  
  37.        
  38.           //==的比較  
  39.         if (lngA == lngB)  
  40.           System.out.println("lngA == lngB");  
  41.         else  
  42.           System.out.println("lngA != lngB (Because of the new operator)");  
  43.        
  44.         if (lngA == lngC)  
  45.           System.out.println("lngA == lngC");  
  46.         else  
  47.           System.out.println("lngA != lngC (Because of the new operator)");  
  48.        
  49.           //equals的比較  
  50.         if (lngA.equals(lngB))  
  51.           System.out.println("lngA.equals(lngB) = true (Same value)");  
  52.         else  
  53.           System.out.println("lngA.equals(lngB) = false");  
  54.        
  55.         if (lngA.equals(lngC))  
  56.           System.out.println("lngA.equals(lngC) = true (Same value)");  
  57.         else  
  58.           System.out.println("lngA.equals(lngC) = false");  
  59.        
  60.         //自定型別  
  61.         myObject1 m1A = new myObject1();  
  62.         myObject1 m1B = new myObject1();  
  63.         myObject2 m2A = new myObject2();  
  64.         myObject2 m2B = new myObject2();  
  65.        
  66.           //==的比較  
  67.         if (m1A == m1B)  
  68.           System.out.println("m1A == m1B");  
  69.         else  
  70.           System.out.println("m1A != m1B (Not same memory address)");  
  71.        
  72.         if (m2A == m2B)  
  73.           System.out.println("m2A == m2B");  
  74.         else  
  75.           System.out.println("m2A != m2B (Not same memory address)");  
  76.        
  77.           //equals的比較  
  78.         if (m1A.equals(m1B))  
  79.           System.out.println("m1A.equals(m1B) = true");  
  80.         else  
  81.           System.out.println("m1A.equals(m1B) = false (Not overwtire equals method)");  
  82.        
  83.         if (m2A.equals(m2B))  
  84.           System.out.println("m2A.equals(m2B) = true (Rewrite equals method)");  
  85.         else  
  86.           System.out.println("m2A.equals(m2B) = false");  
  87.       }  
  88.       public static void main(String[] args) {  
  89.         myEquals myEquals1 = new myEquals();  
  90.       }  
  91.   
  92. }  

執行結果 :
sA == sB (Because of String pool)
sA != sC (Because sC uses new operator)
sA.equals(sB) = true (Because of the same value)
sA.equals(sC) = true (Because of the same value)
lngA != lngB (Because of the new operator)
lngA != lngC (Because of the new operator)
lngA.equals(lngB) = true (Same value)
lngA.equals(lngC) = true (Same value)
m1A != m1B (Not same memory address)
m2A != m2B (Not same memory address)
m1A.equals(m1B) = false (Not overwtire equals method)
m2A.equals(m2B) = true (Rewrite equals method)

補充說明 :
This message was edited 2 times. Last update was at 03/12/2010 10:34:56

[ Py DS ] Ch3 - Data Manipulation with Pandas (Part5)

Source From  Here   Pivot Tables   We have seen how the  GroupBy  abstraction lets us explore relationships within a dataset. A pivot ta...