Skip to content

Instantly share code, notes, and snippets.

@Archina
Last active August 23, 2017 11:38
Show Gist options
  • Save Archina/43c0a807d2c5618bf9d98e644e8c328f to your computer and use it in GitHub Desktop.
Save Archina/43c0a807d2c5618bf9d98e644e8c328f to your computer and use it in GitHub Desktop.
Attempt for an Implementation of the Observer Pattern in Rust
use std::vec::Vec;
use std::rc::{Weak,Rc};
pub trait Observer{
fn on_notify( &self ) -> ();
}
#[derive(Default)]
pub struct Subject{
observers: Vec< Weak <Observer > >,
}
impl Subject{
fn get_obs_index( &self, obs: &Rc< Observer > ) -> Option<usize>{
for iter_observer in self.observers.iter().enumerate() {
let (left,right) = iter_observer;
if right.upgrade().is_some() && Rc::ptr_eq( &right.upgrade().unwrap(), obs){
return Some(left);
}
}
None
}
}
pub trait Observable{
fn notify( &self ) -> ();
fn add_observer( &mut self, obs: Rc<Observer> ) -> ();
fn remove_observer( &mut self, obs: Rc<Observer> ) -> ();
}
impl Observable for Subject{
fn notify( &self ){
for iter in &self.observers {
if iter.upgrade().is_some() {
iter.upgrade().unwrap().on_notify();
}
}
}
fn add_observer( &mut self, obs: Rc<Observer> ){
self.observers.push( Rc::downgrade(&obs) );
}
fn remove_observer( &mut self, obs: Rc<Observer> ){
let found_index = self.get_obs_index(&obs);
if found_index.is_some() {
self.observers.remove( found_index.unwrap() );
}
}
}
#[test]
fn test_something() {
use std::cell::Cell;
struct SampleObs{
name: String,
dy_attr: Cell<i32>,
}
impl Observer for SampleObs{
fn on_notify(&self) -> (){
panic!(
"My name is {} and I am {} ticks old.",
self.name,
self.dy_attr.get()
);
}
}
let mut sub = Subject::default();
let obs = Rc::new(
SampleObs{
name: String::from("Chicken"),
dy_attr: Cell::new(10)
});
sub.add_observer(obs.clone());
sub.remove_observer(obs.clone());
sub.notify();
sub.add_observer(obs.clone());
drop(obs);
sub.notify();
assert_ne!(42, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment