观察者模式Java - 使用线程的多个观察者

时间:2013-03-17 12:54:16

标签: java multithreading oop inheritance observer-pattern

我正在努力学习所有主要的设计模式。我刚开始学习java中的多线程。这是观察者模式代码,其中有多个观察者和observable正在运行一段时间。我遇到以下两个问题:

  1. 当调用notifyObservers时,即使我的观察者正在访问可观察值的getter,我也必须将新值传递给它。如果我不这样做,那么观察者获取/打印值为null。我创建了一个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(); }
                }
            }
        }
    }
    
  3. 我非常感谢关于这些概念的最佳实践的任何指示/建议/意见。

    请帮忙。

2 个答案:

答案 0 :(得分:3)

  1. 您无需将Observable实例引用传递给观察者;这实际上是一个坏主意,因为您在Observable方法中获得了update()实例和修改后的值的引用。此外,如果您未将观察者绑定到特定的Observable实例,则可以将其附加到其他Observable而无需任何修改。

  2. 对于使用多个观察者,您不一定需要多个类。在您的情况下,您可以使用同一类的多个实例来实现您想要的功能。

答案 1 :(得分: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. 这将允许您访问您需要的observable上的任何方法,这样您就可以获得可能已更改的所有值并相应地更新。

    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(); }
            }
        }
    }
    }