2013-03-17 235 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