How can I implement the observer pattern in Rust?

后端 未结 5 900
轻奢々
轻奢々 2020-12-28 17:01

I have an observable collection and an observer. I want the observer to be a trait implementation of trait Observer. The observable object should be able to not

5条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-28 17:41

    I wrote this answer if you are still interested about it:

    I tried this way, and it worked fine with me, it is as simple as:

    • Define your object struct
    • Define your Listeners,
    • Define your standard functions, let's call them Extensions,
    • Define the add Emitter option to the Extensions by execution Self::Fn

    The same code I used in the playground is below, I just solved it in the rust forum:

    // 1. Define your object
    //#[derive(Debug)]
    pub struct Counter {
     count: i32,
    }
    
    // 2. (Optional), if do not want to use `#[derive(Debug)]` 
    //    you can define your own debug/release format
    impl std::fmt::Debug for Counter {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(f, "Counter `count` is: {}", self.count)
        }
    }
    
    // 3. Define your Listeners trait 
    trait EventListener {
         fn on_squared() {
            println!("Counter squared")
         }
         fn on_increased(amount: i32) {
            println!("Counter increased by {}", amount)
         }
         fn on_decreased(self, amount: i32);
    }
    
    // 4. Implement your Listeners trait to your object
    impl EventListener for Counter {
        fn on_decreased(self, amount: i32) {
            println!("Counter reduced from {} to {}", &self.count, &self.count - amount)
        }
    }
    
    // 5. (Recommended), Define your standard functions/Extensions/Emitters
    //    trait signatures
    trait EventEmitter {
        fn square(&mut self);
        fn increase(&mut self, amount: i32);
        fn decrease(&mut self, amount: i32);
        fn change_by(&mut self, amount: i32);
    }
    
    // 6. Implement your standard functions/Extensions/Emitters trait to your object
    impl EventEmitter for Counter {
        fn square(&mut self) { 
            self.count = self.count.pow(2);
            Self::on_squared();      // This is Event Emitter, calling the Listner
        }
        fn increase(&mut self, amount: i32) { 
            self.count = self.count + amount; 
            Self::on_increased(amount);   // This is Event Emitter, calling the Listner
        }
        fn decrease(&mut self, amount: i32) {
            let initial_value = self.count;
            self.count = self.count - amount;
            Self::on_decreased(Self {count: initial_value}, amount);  // This is Event Emitter, calling the Listner
        }
        fn change_by(&mut self, amount: i32) {
            let initial_value = self.count;
            self.count = self.count + amount;
            match amount {
                x if x > 0 => Self::on_increased(amount),   // This is Event Emitter, calling the Listner
                x if x < 0 => Self::on_decreased(Self {count: initial_value},  // This is Event Emitter, calling the Listneramount.abs()),
                _   => println!("No changes")
            }
        }
    }
    
    // 7. Build your main function
    fn main() {
        let mut x = Counter { count: 5 };
        println!("Counter started at: {:#?}", x.count);
        x.square();   // Call the extension, which will automatically trigger the listner
        println!("{:?}", x);
        x.increase(3);
        println!("{:?}", x);
        x.decrease(2);
        println!("{:?}", x);
        x.change_by(-1);
        println!("{:?}", x);
    }
    

    And got the below output:

    Counter started at: 5
    Counter squared
    Counter `count` is: 25
    Counter increased by 3
    Counter `count` is: 28
    Counter reduced from 28 to 26
    Counter `count` is: 26
    Counter reduced from 26 to 25
    Counter `count` is: 25
    

提交回复
热议问题