2013-03-17 301 views
4

我想學習所有主要的設計模式。我剛開始學習java中的多線程。這是觀察者模式代碼,其中有多個觀察者& observable正在while循環中運行。我有以下兩個問題:觀察者模式Java - 使用線程的多個觀察者

  1. 當調用notifyObservers時,即使我的觀察者訪問可觀察值的getter,我也必須將新值傳遞給它。如果我不這樣做,那麼觀察者得到/打印值爲空。我創建了一個setter函數來演示它。
  2. 我創建了兩個觀察者&,顯然他們兩人的大部分代碼是相似的。我不確定如何實現新的觀察者或創建觀察者列表而不復制我的代碼。我創建了一個basicObserver &試圖在MyObserver3中繼承它,但我不確定我是如何實現它的。

    import java.util.Observable; 
    import java.util.Observer; 
    
    public class ObserverPatternMultipleObserversUsingThreads 
    { 
        public static void main(String[] args) 
        { 
         ObservableValue observableObj = new ObservableValue(10); 
    
         MyObserver1 observer1 = new MyObserver1(observableObj); 
         MyObserver2 observer2 = new MyObserver2(observableObj); 
         MyObserver3 observer3 = new MyObserver3(observableObj); 
    
         observableObj.addObserver(observer1); 
         observableObj.addObserver(observer2); 
    
         observableObj.start(); 
    
         System.out.println("Calling Listeners"); 
    
         observer1.printObservablesValue(); 
         observer2.printObservablesValue(); 
    
         System.out.println("Main thread says: Sleeping for 3 second(s)"); 
    
         try 
         { 
          Thread.sleep(3000); 
         } 
    
         catch (InterruptedException e) 
         { 
          e.printStackTrace(); 
         } 
    
         System.out.println("Main thread says: Going to change Observables Value"); 
    
         observableObj.setValue(20); 
        } 
    } 
    
    class basicObserver 
    { 
        private ObservableValue obsValObj = null; 
    
        public basicObserver(ObservableValue obsVal) 
        { 
         this.obsValObj = obsVal; 
        } 
    
        public void printObservablesValue() 
        { 
         System.out.println("Observer says: [" + obsValObj.getValue() + "]");  
        } 
    
        public void update(Observable o, Object arg) 
        { 
         Integer count = (Integer) arg; 
         System.out.println("Observer says: Value changed to: [" + count + "]"); 
        } 
    } 
    
    class MyObserver3 extends basicObserver implements Observer 
    { 
        public MyObserver3(ObservableValue obsVal) 
        { 
         super(obsVal); 
        } 
    } 
    
    class MyObserver1 implements Observer 
    { 
        private ObservableValue obsValObj = null; 
    
        public MyObserver1(ObservableValue obsVal) 
        { 
         this.obsValObj = obsVal; 
        } 
    
        public void printObservablesValue() 
        { 
         System.out.println("MyObserver1 says: [" + obsValObj.getValue() + "]"); 
        } 
    
        public void update(Observable o, Object arg) 
        { 
         Integer count = (Integer) arg; 
         System.out.println("MyObserver1 says: Value changed to: [" + count + "]"); 
        } 
    } 
    
    class MyObserver2 implements Observer 
    { 
        private ObservableValue obsValObj = null; 
    
        public MyObserver2(ObservableValue obsVal) 
        { 
         this.obsValObj = obsVal; 
        } 
    
        public void printObservablesValue() 
        { 
         System.out.println("MyObserver2 says: [" + obsValObj.getValue() + "]"); 
        } 
    
        public void update(Observable o, Object arg) 
        { 
         Integer count = (Integer) arg; 
         System.out.println("MyObserver2 says: Value changed to: [" + count + "]"); 
        } 
    } 
    
    class ObservableValue extends Observable implements Runnable 
    { 
        private int n = 0; 
    
        public ObservableValue(int x) 
        { 
         this.n = x; 
        } 
    
        public int getValue() 
        { 
         return n; 
        } 
    
        public void setValue(int x) 
        { 
         this.n = x; 
         setChanged(); 
         System.out.println("ObservableValue says: setChanged() has been called"); 
    
    //  notifyObservers(new Integer(this.n)); 
         notifyObservers();                 // makes the observers print null 
         System.out.println("ObservableValue says: notifyObservers() has been called"); 
        } 
    
        public void start() 
        { 
         new Thread(this).start(); 
        } 
    
        public void run() 
        { 
         int count = -1; 
         int a=0, b=0; 
    
         while(a==b) 
         { 
          if(count != n) 
          { 
           count = n; 
           System.out.println("ObservableValue says: My count is: [" + count + "]"); 
    
           count++; 
           System.out.println("ObservableValue says: Now my count is: [" + count + "]"); 
           setChanged(); 
           System.out.println("ObservableValue says: setChanged() has been called"); 
    
           notifyObservers(new Integer(count)); 
           System.out.println("ObservableValue says: notifyObservers() has been called"); 
    
           System.out.println("ObservableValue says: Sleeping for 5 second(s)"); 
    
           try 
           { 
            Thread.sleep(5000); 
           } 
    
           catch (InterruptedException e) { e.printStackTrace(); } 
          } 
         } 
        } 
    } 
    

我真的很感激,關於這些概念的最佳實踐的指針/諮詢/評論。

請幫忙。

+0

[本教程](http://www.java2s.com/Code/Java/Design-Pattern/AsimpledemoofObservableandObserver.htm)可能很有用。 – 2013-03-17 13:30:28

+0

謝謝@SazzadurRahaman。我理解這個概念。我的問題是爲什麼我的觀察者沒有得到最新的值,即使我在改變observable的值之後調用setChanged()和notifyObservers()。 – MdT 2013-03-17 22:45:06

回答

3
  1. 您不需要將Observable實例引用傳遞給觀察者;這實際上是一個糟糕的主意,因爲您會參照Observable實例和update()方法中的修改值。另外,如果您沒有將觀察者綁定到特定的Observable實例,則可以將它們附加到其他Observable,而不做任何修改。

  2. 對於使用多個觀察者,您不一定需要多個類。就你而言,你可能可以通過同一個類的多個實例來實現你想要的。

+0

謝謝@Costi Ciudatu。我有你的第二點。在你的第一點中你提到了Observable實例不應該被傳遞。你在談論notifyObservers方法,對吧?這正是我的觀點。我知道我不應該這樣做,但如果我不這樣做,我的觀察員沒有獲得價值。爲什麼他們無法訪問最新的價值 - 正是我想要調試的。 – MdT 2013-03-17 22:48:53

+0

不,我在說你不應該將可觀察的實例作爲構造函數參數傳遞給觀察者。他們在'update()'方法中獲取他們需要的所有信息,這使得它們依賴於observable的某些實例是無用的限制。 – 2013-03-17 23:57:36

+0

明白了。感謝您的建議。 – MdT 2013-03-18 00:33:04

2
  1. 試着改變你的更新方法如下:

    public void update(Observable o, Object arg) 
    { 
        if (o instanceof ObservableValue){ 
         ObservableValue obs = (ObservableValue) o; 
         System.out.println("MyObserver1 says: Value changed to: [" + obs.getValue() + "]"); 
        }else{ 
         System.out.println("The observable object was not of the correct type"); 
        } 
    
    } 
    

這將允許您訪問您觀察到的任何方法,你需要這樣你可以得到所有的值這可能已經改變並相應地更新。

2我沒有看到你的類之間有太大的區別,你能不能只爲這些觀察者創建一個新的實例,而不是爲每個類創建一個完整的類?

我已經刪除了我認爲不需要的類,並說明了如何使用一個觀察者類完成此操作(除非您需要每個類都有不同的功能)。他們被編號爲以前的樣子。

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

public class ObserverPatternMultipleObserversUsingThreads 
{ 
    public static void main(String[] args) 
{ 
    ObservableValue observableObj = new ObservableValue(10); 

    MyObserver observer1 = new MyObserver(observableObj); 
    MyObserver observer2 = new MyObserver(observableObj); 

    observableObj.addObserver(observer1); 
    observableObj.addObserver(observer2); 

    observableObj.start(); 

    System.out.println("Calling Listeners"); 

    observer1.printObservablesValue(); 
    observer2.printObservablesValue(); 

    System.out.println("Main thread says: Sleeping for 3 second(s)"); 

    try 
    { 
     Thread.sleep(3000); 
    } 

    catch (InterruptedException e) 
    { 
     e.printStackTrace(); 
    } 

    System.out.println("Main thread says: Going to change Observables Value"); 

    observableObj.setValue(20); 
    } 
} 


class MyObserver implements Observer 
{ 
static int numberOfObservers = 0; 
private ObservableValue obsValObj = null; 
private int observerNumber; 

public MyObserver(ObservableValue obsVal) 
{ 
    numberOfObservers++; 
    observerNumber = numberOfObservers; 
    this.obsValObj = obsVal; 
} 

public void printObservablesValue() 
{ 
    System.out.println("MyObserver"+observerNumber+" says: [" + obsValObj.getValue() + "]"); 
} 

public void update(Observable o, Object arg) 
{ 


    if (o instanceof ObservableValue){ 
     ObservableValue obs = (ObservableValue) o; 
     System.out.println("MyObserver"+observerNumber+" says: Value changed to: [" + obs.getValue() + "]"); 
    }else{ 
     System.out.println("The observable object was not of the correct type"); 
    } 

} 
} 

class ObservableValue extends Observable implements Runnable 
{ 
    private int n = 0; 

    public ObservableValue(int x) 
{ 
    this.n = x; 
} 

public int getValue() 
{ 
    return n; 
} 

public void setValue(int x) 
{ 
    this.n = x; 
    setChanged(); 
    System.out.println("ObservableValue says: setChanged() has been called"); 

//  notifyObservers(new Integer(this.n)); 
    notifyObservers();                  // makes the observers print null 
    System.out.println("ObservableValue says: notifyObservers() has been called"); 
} 

public void start() 
{ 
    new Thread(this).start(); 
} 

public void run() 
{ 
    int count = -1; 
    int a=0, b=0; 

    while(a==b) 
    { 
     if(count != n) 
     { 
      count = n; 
      System.out.println("ObservableValue says: My count is: [" + count + "]"); 

      count++; 
      System.out.println("ObservableValue says: Now my count is: [" + count + "]"); 
      setChanged(); 
      System.out.println("ObservableValue says: setChanged() has been called"); 

      notifyObservers(new Integer(count)); 
      System.out.println("ObservableValue says: notifyObservers() has been called"); 

      System.out.println("ObservableValue says: Sleeping for 5 second(s)"); 

      try 
      { 
       Thread.sleep(5000); 
      } 

      catch (InterruptedException e) { e.printStackTrace(); } 
     } 
    } 
} 
} 
+0

請原諒我的代碼格式,我似乎在這裏與stackoverflow代碼視圖有點爭鬥,試圖解決它。 – ThePerson 2013-03-17 13:29:26

+0

謝謝@NutterzUK。我運行了你的代碼。觀察者沒有得到可觀察值的更新值。 – MdT 2013-03-17 22:42:27

+0

對不起,我想我可能會困惑,然後.. 20?這表明對我來說,也許我誤解了你的意思。 – ThePerson 2013-03-18 10:25:21