argamanza
argamanza

Reputation: 1142

Trying to create a Listener pattern style class, observers won't get notified

I'm now learning about the Listener or Observer-Observable design patter, i tried to implement my own class using the supplied Java library Observer interface and Observable class.

My Observable subject is an empty class that extends Observable.

Here are my two Observer classes:

public class CatObserver implements Observer {
    private String status = "Sleeping...";
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Updated!");
        this.status = "Awake!";
    }

    public void getStatus(){
        System.out.println(status);
    }
}

public class DogObserver implements Observer {
    private String status = "Sleeping...";
    @Override
    public void update(Observable o, Object arg) {
        this.status = "Awake!";
    }

    public void getStatus(){
        System.out.println(status);
    }
}

Here is my main program:

public class Listener {
    public static void main(String[] args) {
        AnimalSubject subject = new AnimalSubject();

        CatObserver mitsy = new CatObserver();
        DogObserver ozil = new DogObserver();

        mitsy.getStatus();
        ozil.getStatus();

        subject.addObserver(mitsy);
        subject.addObserver(ozil);

        synchronized (subject){
            subject.notifyAll();
        }

        mitsy.getStatus();
        ozil.getStatus();

    }

My output is 4 lines of "Sleeping...", when it should be 2 lines of "Sleeping..." and 2 lines of "Awake!".

When debugging it won't even go into the update() functions.

What am I doing wrong here?

Upvotes: 1

Views: 58

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Your code is only half done as you're not using the Observable class anywhere that we can see. The Observer/Observable interface/class pair don't work with Object's notifyAll(). Instead you must create a class that extends the Observable abstract class and then call the Observable's proper notify method, notifyObservers(...), when appropriate.

Edit: I now see that you are using Observable but you don't show the code, but rather state that it's empty. Show your code, and make it "non-empty" where in fact you call the method above when its state changes.

Something like...

import java.util.*;

public class Listener {
   public static void main(String[] args) {
      AnimalSubject subject = new AnimalSubject("My Dog");

      DogObserver ozil = new DogObserver();

      ozil.getStatus();

      subject.addObserver(ozil);

      subject.setStatus(Status.AWAKE);
      subject.setStatus(Status.EATING);

      ozil.getStatus();

   }

}

class DogObserver implements Observer {
   private Status status = Status.ASLEEP;

   @Override
   public void update(Observable o, Object arg) {
      status = ((StatusEvent) arg).getNewValue();
      getStatus();
   }

   public void getStatus() {
      System.out.println("Status: " + status);
   }
}

class AnimalSubject extends Observable {
   private String name;
   private Status status = Status.ASLEEP;

   public AnimalSubject(String name) {
      this.name = name;
   }

   public void setStatus(Status status) {
      Status oldValue = this.status;
      Status newValue = status;
      if (oldValue.equals(newValue)) {
         return;
      }
      this.status = status;
      StatusEvent event = new StatusEvent(this, oldValue, newValue);
      setChanged();
      notifyObservers(event);
   }

   public Status getStatus() {
      return status;
   }

   public String getName() {
      return name;
   }
}


enum Status {
   ASLEEP, AWAKE, EATING
}

class StatusEvent {
   private Object source;
   private Status oldValue;
   private Status newValue;

   public StatusEvent(Object source, Status oldValue, Status newValue) {
      this.source = source;
      this.oldValue = oldValue;
      this.newValue = newValue;
   }

   public Object getSource() {
      return source;
   }

   public Status getOldValue() {
      return oldValue;
   }

   public Status getNewValue() {
      return newValue;
   }

}

Upvotes: 1

Related Questions