J.Doe
J.Doe

Reputation: 23

Working with observer pattern

I have an observer class below. my question is how could I set up up this class to listen(observe) to more than 1 subject?

    public class Observer2 implements Observer {
      private Subject robot;


      public Observer2(Subject robot){
       this.robot = robot;
       robot.registerObserver(this);
    }

      @Override
      public void update(){}
}

Upvotes: 1

Views: 402

Answers (4)

Jul10
Jul10

Reputation: 503

A ConcreteObserver can observe more than one Subject simply calling many times the attach method that the Subjects provide.
If the question is instead:

"How can a ConcreteObserver observe many ConcreteSubjects of different kind that have different types of state?"

The answer is that in the ConcreteObserver the update method must be overloaded to manage many times equal to the types of states that the ConcreteObserver has to observe.
The ConcreteObserver must have also an array of states to store the observed states of the Subjects, with some mechanism to avoid that state of the same type coming from different Subject influence the state of each other.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727137

Use Java's Observer and Observable, which are set up for proper handling of multiple subjects:

class Robot extends Observable {
    public void act() {
        notifyObservers("Run!");
    }
}
class Cyborg extends Observable {
    public void act() {
        notifyObservers("Hide!");
    }
}

public class MyObserver implements Observer {
    @Override
    public void update(Observable subj, Object arg) {
        if (subj instanceof Robot) {
            System.out.println("Scary robot says " + arg);
        } else if (subj instanceof Cyborg) {
            System.out.println("Lovely cyborg says " + arg);
        } else {
            System.out.println("What's this? " + arg);
        }
    }
}

Registration is done differently:

// Construct observables
Robot r = new Robot();
Cyborg c = new Cyborg();
// Add observer to both of them
MyObserver o = new MyObserver();
r.addObserver(o);
c.addObserver(o);
r.act();
c.act();

Upvotes: 0

Menelaos Kotsollaris
Menelaos Kotsollaris

Reputation: 5506

You can have a Subject class which stores all the observers in a list.

public abstract class Subject
{
    private ArrayList<Observer> observerList = new ArrayList<>();

    public void attach(Observer observer)
    {
        observerList.add(observer);
    }

    /**
     * Notifies observers to run execute
     */
    protected void notifyObservers()
    {
        for(int i = 0; i < observerList.size(); i++)
        {
            observerList.get(i).update();
        }
    }
}

The typical Observer interface:

interface Observer
{
    void update();
}

Thereafter, you can trigger the observers using the notifyObservers() method.

Upvotes: 1

Leo Aso
Leo Aso

Reputation: 12513

Use a set.

public class MultiObserver extends Observer {
    private final Set<Subject> observed = new HashSet<>();

    public void observe(Subject s) {
        if (observed.add(s))
            s.registerObserver(this);
    }
}

Upvotes: 0

Related Questions