exercises

Log | Files | Refs | README

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("<", "&lt;").replace(">", "&gt;")
     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 }