forked from eliovir/rust-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdesign_pattern-observer.rs
102 lines (97 loc) · 2.49 KB
/
design_pattern-observer.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Example of design pattern inspired from Head First Design Patterns
//!
//! Tested with rust-1.3.0
//!
//! @author Eliovir <http://github.com/~eliovir>
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>
//!
//! @since 2014-04-18
//! TODO : add/delete/notify observers of different types
//! TODO : display Observable temperature on Observer.update()
// Observer
trait Observer {
fn update(&self);
}
// Observable memorizes all Observers and send notifications
trait Observable<'a, T: Observer> {
fn add_observer(&mut self, observer: &'a T);
fn delete_observer(&mut self, observer: &'a T);
fn notify_observers(&self);
}
// Define Observer and Observable
struct Display {
name: String,
}
struct Weather<'a, T:'a> {
temperature: f64,
observers: Vec<&'a T>
}
impl<'a> Weather<'a, Display> {
fn set_temperature(&mut self, temperature: f64) {
self.temperature = temperature;
self.notify_observers();
}
}
/*
* Traits implementations
*/
//impl<U: Observable> Observer<U> for Display<U> {
impl Observer for Display {
fn update(&self) {
println!("Display {} updated!", self.name);
}
}
impl Display {
fn new(name: String) -> Display {
Display{name: name}
}
}
impl std::cmp::PartialEq for Display {
fn eq(&self, other: &Display) -> bool {
self.name == other.name
}
}
impl std::fmt::Display for Display {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Display {}", self.name)
}
}
impl<'a, T: Observer+PartialEq+std::fmt::Display> Observable<'a, T> for Weather<'a, T> {
fn add_observer(&mut self, observer: &'a T) {
println!("add_observer({});", observer);
self.observers.push(observer);
}
fn delete_observer(&mut self, observer: &'a T) {
let mut index = 0;
let mut found = false;
for &obs in self.observers.iter() {
if obs == observer {
println!("delete_observer({});", observer);
found = true;
break;
}
index += 1;
}
if found {
self.observers.remove(index);
}
}
fn notify_observers(&self) {
for &observer in self.observers.iter() {
observer.update();
}
}
}
fn main() {
// reference must be valid for the block
// so all bindings display must exist before weather
let display = Display::new("Desktop".to_string());
let display2 = Display::new("Desktop2".to_string());
let mut weather = Weather{temperature: 19.0, observers: Vec::new()};
weather.add_observer(&display);
weather.add_observer(&display2);
weather.set_temperature(20.0);
weather.delete_observer(&display2);
weather.set_temperature(21.0);
}