上QQ阅读APP看书,第一时间看更新
How to do it...
In the src/bin folder, create a file called builder.rs
Add all of the following code and run it with cargo run --bin builder:
1 fn main() {
2 // We can easily create different configurations
3 let normal_burger = BurgerBuilder::new().build();
4 let cheese_burger = BurgerBuilder::new()
.cheese(true)
.salad(false)
.build();
5 let veggie_bigmac = BurgerBuilder::new()
.vegetarian(true)
.patty_count(2)
.build();
6
7 if let Ok(normal_burger) = normal_burger {
8 normal_burger.print();
9 }
10 if let Ok(cheese_burger) = cheese_burger {
11 cheese_burger.print();
12 }
13 if let Ok(veggie_bigmac) = veggie_bigmac {
14 veggie_bigmac.print();
15 }
16
17 // Our builder can perform a check for
18 // invalid configurations
19 let invalid_burger = BurgerBuilder::new()
.vegetarian(true)
.bacon(true)
.build();
20 if let Err(error) = invalid_burger {
21 println!("Failed to print burger: {}", error);
22 }
23
24 // If we omit the last step, we can reuse our builder
25 let cheese_burger_builder = BurgerBuilder::new().cheese(true);
26 for i in 1..10 {
27 let cheese_burger = cheese_burger_builder.build();
28 if let Ok(cheese_burger) = cheese_burger {
29 println!("cheese burger number {} is ready!", i);
30 cheese_burger.print();
31 }
32 }
33 }
This is the configurable object:
35 struct Burger {
36 patty_count: i32,
37 vegetarian: bool,
38 cheese: bool,
39 bacon: bool,
40 salad: bool,
41 }
42 impl Burger {
43 // This method is just here for illustrative purposes
44 fn print(&self) {
45 let pretty_patties = if self.patty_count == 1 {
46 "patty"
47 } else {
48 "patties"
49 };
50 let pretty_bool = |val| if val { "" } else { "no " };
51 let pretty_vegetarian = if self.vegetarian { "vegetarian "
}
else { "" };
52 println!(
53 "This is a {}burger with {} {}, {}cheese, {}bacon and
{}salad",
54 pretty_vegetarian,
55 self.patty_count,
56 pretty_patties,
57 pretty_bool(self.cheese),
58 pretty_bool(self.bacon),
59 pretty_bool(self.salad)
60 )
61 }
62 }
And this is the builder itself. It is used to configure and create a Burger:
64 struct BurgerBuilder {
65 patty_count: i32,
66 vegetarian: bool,
67 cheese: bool,
68 bacon: bool,
69 salad: bool,
70 }
71 impl BurgerBuilder {
72 // in the constructor, we can specify
73 // the standard values
74 fn new() -> Self {
75 BurgerBuilder {
76 patty_count: 1,
77 vegetarian: false,
78 cheese: false,
79 bacon: false,
80 salad: true,
81 }
82 }
83
84 // Now we have to define a method for every
85 // configurable value
86 fn patty_count(mut self, val: i32) -> Self {
87 self.patty_count = val;
88 self
89 }
90
91 fn vegetarian(mut self, val: bool) -> Self {
92 self.vegetarian = val;
93 self
94 }
95 fn cheese(mut self, val: bool) -> Self {
96 self.cheese = val;
97 self
98 }
99 fn bacon(mut self, val: bool) -> Self {
100 self.bacon = val;
101 self
102 }
103 fn salad(mut self, val: bool) -> Self {
104 self.salad = val;
105 self
106 }
107
108 // The final method actually constructs our object
109 fn build(&self) -> Result<Burger, String> {
110 let burger = Burger {
111 patty_count: self.patty_count,
112 vegetarian: self.vegetarian,
113 cheese: self.cheese,
114 bacon: self.bacon,
115 salad: self.salad,
116 };
117 // Check for invalid configuration
118 if burger.vegetarian && burger.bacon {
119 Err("Sorry, but we don't server vegetarian bacon
yet".to_string())
120 } else {
121 Ok(burger)
122 }
123 }
124 }