-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathdesign_pattern-decorator2.rs
73 lines (63 loc) · 1.86 KB
/
design_pattern-decorator2.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
//! Example of design pattern inspired from Head First Design Patterns
//!
//! Tested with rust-1.41.1-nightly
//!
//! @author Eliovir <http://github.com/~eliovir>
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>
//!
//! @since 2014-04-12
// This design pattern needs a common trait for Drinks and Ingredients
trait Drinkable {
fn description(&self) -> String;
fn price(&self) -> f64;
}
struct Drink<'a> {
price: f64,
description: &'a str
}
impl<'a> Drinkable for Drink<'a> {
fn description(&self) -> String {
self.description.to_string()
}
fn price(&self) -> f64 {
self.price
}
}
impl<'a> Drink<'a> {
// The "constructor", optional but useful!
pub fn new(description: &'a str, price: f64) -> Drink<'a> {
Drink { description: description, price: price }
}
}
struct Ingredient<'a> {
description: &'a str,
price: f64,
// to decorate an struct, it must have the common trait
drink: Box<dyn Drinkable + 'a>,
}
impl<'a> Drinkable for Ingredient<'a> {
fn description(&self) -> String {
let mut description = self.drink.description();
description.push_str(", ");
description.push_str(self.description);
description.clone()
}
fn price(&self) -> f64 {
self.price + self.drink.price()
}
}
impl<'a> Ingredient<'a> {
// The "constructor", optional but useful!
pub fn new(description: &'a str, price: f64, drink: Box<dyn Drinkable + 'a>) -> Ingredient<'a> {
Ingredient { description: description, price: price, drink: drink }
}
}
fn main() {
let columbia = Drink::new("Columbia", 0.89);
println!("{} => {}", columbia.description(), columbia.price());
let chocolate = Ingredient::new("chocolate", 0.2, Box::new(columbia));
println!("{} => {}", chocolate.description(), chocolate.price());
let chantilly = Ingredient::new("chantilly", 0.1, Box::new(chocolate));
println!("{} => {}", chantilly.description(), chantilly.price());
}