I have an observable collection and observer. I want observer to be a trait implementation of trait Observer. Observable object should be able to notify each of it's observer when some event appear. Code below should explain my intentions more detailed:
struct A {
observables: Vec<Observable>,
}
impl A {
fn new() -> A {
A {
observables: vec![],
}
}
}
trait Observer {
fn event(&mut self, &String);
}
impl Observer for A {
fn event(&mut self, ev: &String) {
println!("Got event from observable: {}", ev);
}
}
struct Observable {
observers: Vec<Observer>, // How to contain references to observers? (this line is invalid)
}
impl Observable {
fn new() -> Observable {
Observable {
observers: Vec::new(),
}
}
fn add_observer(&mut self, o: &Observer) { // incorrect line too
self.observers.push(o);
}
fn notify_observers(&self, ev: &String) {
for o in &mut self.observers {
o.event(ev);
}
}
}
This is just a mock-up of what I wanna do. I had a code like this in java, python, cpp but I don't know how to implement the observer pattern in rust.
You'll either need to store Box<Observer> values, if the observers are entirely owned by Observable, or Rc<Observer> if ownership must be shared with other parts of the code (in which case &mut self won't work, and each implementation of Observer will require interior mutability using Cell/RefCell). The final option would be &Observer, but that only works if you can guarantee that all observers will outlive the Observable object that stores pointers to them, which seems unlikely given the pattern being implemented.
I found another option - Pull mode (returning events from function and handling them), that Matthieu M. is talking about on Stackoverflow, cleaner and simpler than observer pattern.