bridge_pattern.rs (2598B)
1 //! The Bridge Pattern: 2 //! The abstraction defines what the display can do. The implementation defines 3 //! how formatting works. 4 5 use crate::Expression; 6 7 /// The Display trait speaks in calculator domain concepts: results, errors, 8 /// expressions. 9 pub trait Display { 10 fn show_result(&self, result: f64); 11 fn show_error(&self, error: &str); 12 fn show_expression(&self, expression: &dyn Expression); 13 } 14 15 /// The DisplayImplementation trait spesaks in formatting primitives: text 16 /// and formatted values. 17 pub trait DisplayImplementation { 18 fn display_text(&self, text: &str); 19 fn display_formatted(&self, value: f64, format: &str); 20 } 21 22 /// The Bridge connects them through composition: 23 pub struct CalculatorDisplay { 24 implementation: Box<dyn DisplayImplementation>, 25 } 26 27 impl Display for CalculatorDisplay { 28 fn show_result(&self, result: f64) { 29 self.implementation 30 .display_formatted(result, "Result: {:.10g}"); 31 } 32 33 fn show_error(&self, error: &str) { 34 self.implementation 35 .display_text(&format!("Error: {}", error)); 36 } 37 38 fn show_expression(&self, expression: &dyn Expression) { 39 self.implementation 40 .display_text(&format!("Expression: {}", expression.to_string())); 41 } 42 } 43 44 /// Concrete output mechanisms: 45 /// 46 /// The console implementation writes plain text to standard output: 47 pub struct ConsoleDisplay; 48 49 impl DisplayImplementation for ConsoleDisplay { 50 fn display_text(&self, text: &str) { 51 println!("{}", text); 52 } 53 54 fn display_formatted(&self, value: f64, format: &str) { 55 println!("{}", format.replace("{:.10g}", &format!("{:.10}", value))) 56 } 57 } 58 59 /// The HTML implementation wraps output in HTML elements: 60 pub struct HtmlDisplay; 61 62 impl DisplayImplementation for HtmlDisplay { 63 fn display_text(&self, text: &str) { 64 println!( 65 "<div>{}</div>", 66 text.replace("<", "<").replace(">", ">") 67 ); 68 } 69 70 fn display_formatted(&self, value: f64, format: &str) { 71 let formatted = format.replace("{:.10g}", &format!("{:.10}", value)); 72 println!("<div class=\"result\">{}</div>", formatted); 73 } 74 } 75 76 /// The JSON implementation produces machine-readable output, making it easy 77 /// to use the output in other programs 78 pub struct JsonDisplay; 79 80 impl DisplayImplementation for JsonDisplay { 81 fn display_text(&self, text: &str) { 82 println!("{{\"text\": \"{}\"}}", text.replace("\"", "\\\"")); 83 } 84 85 fn display_formatted(&self, value: f64, format: &str) { 86 println!("{{\"result\": {:.10}}}", value); 87 } 88 }