Skip to content

Commit 16b6e08

Browse files
committed
Add dependency inversion
1 parent 6e2aaa1 commit 16b6e08

File tree

4 files changed

+287
-1
lines changed

4 files changed

+287
-1
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use std::cell::RefCell;
2+
3+
pub struct Order<'a> {
4+
pub items: Vec<&'a str>,
5+
pub quantities: Vec<u32>,
6+
pub prices: Vec<f32>,
7+
pub status: &'a str,
8+
}
9+
10+
impl<'a> Order<'a> {
11+
pub fn new() -> Self {
12+
Self { items: vec![], quantities: vec![], prices: vec![], status: "open" }
13+
}
14+
15+
pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) {
16+
self.items.push(name);
17+
self.quantities.push(quantity);
18+
self.prices.push(price);
19+
}
20+
21+
pub fn total_price(&self) -> f32 {
22+
let mut total: f32 = 0.0;
23+
24+
for (i, price) in self.prices.iter().enumerate() {
25+
total += self.quantities[i] as f32 * price;
26+
}
27+
28+
total
29+
}
30+
}
31+
32+
pub trait Authorizer {
33+
fn is_authorized(&self) -> bool;
34+
}
35+
36+
pub struct SMSAuthorizer {
37+
pub authorized: bool,
38+
}
39+
40+
impl SMSAuthorizer {
41+
pub fn new() -> Self {
42+
Self { authorized: false }
43+
}
44+
45+
pub fn verify_code(&mut self, code: u32) {
46+
println!("Verifying SMS code {code}");
47+
self.authorized = true;
48+
}
49+
}
50+
51+
impl Authorizer for SMSAuthorizer {
52+
fn is_authorized(&self) -> bool {
53+
self.authorized
54+
}
55+
}
56+
57+
pub struct AuthorizerRobot {
58+
pub authorized: bool,
59+
}
60+
61+
impl AuthorizerRobot {
62+
pub fn new() -> Self {
63+
Self { authorized: false }
64+
}
65+
66+
pub fn not_a_robot(&mut self) {
67+
println!("Are you a robot?");
68+
self.authorized = true;
69+
}
70+
}
71+
72+
impl Authorizer for AuthorizerRobot {
73+
fn is_authorized(&self) -> bool {
74+
self.authorized
75+
}
76+
}
77+
78+
pub trait PaymentProcessor {
79+
fn pay(&self, order: &mut Order);
80+
}
81+
82+
pub struct DebitPaymentProcessor<'a> {
83+
pub security_code: &'a str,
84+
pub authorizer: &'a RefCell<SMSAuthorizer>,
85+
}
86+
87+
impl<'a> DebitPaymentProcessor<'a> {
88+
pub fn new(security_code: &'a str, authorizer: &'a RefCell<SMSAuthorizer>) -> Self {
89+
Self { security_code, authorizer }
90+
}
91+
}
92+
93+
impl PaymentProcessor for DebitPaymentProcessor<'_> {
94+
fn pay(&self, order: &mut Order) {
95+
if !self.authorizer.borrow().is_authorized() {
96+
panic!("Not authorized");
97+
}
98+
99+
println!("Processing debit payment type");
100+
println!("Verifying security code: {}", {self.security_code});
101+
order.status = "paid";
102+
}
103+
}
104+
105+
pub struct CreditPaymentProcessor<'a> {
106+
pub security_code: &'a str,
107+
}
108+
109+
impl<'a> CreditPaymentProcessor<'a> {
110+
pub fn new(security_code: &'a str) -> Self {
111+
Self { security_code }
112+
}
113+
}
114+
115+
impl PaymentProcessor for CreditPaymentProcessor<'_> {
116+
fn pay(&self, order: &mut Order) {
117+
println!("Processing credit payment type");
118+
println!("Verifying security code: {}", {self.security_code});
119+
order.status = "paid";
120+
}
121+
}
122+
123+
pub struct PaypalPaymentProcessor<'a> {
124+
pub email_address: &'a str,
125+
pub authorizer: &'a RefCell<dyn Authorizer>,
126+
}
127+
128+
impl<'a> PaypalPaymentProcessor<'a> {
129+
pub fn new(email_address: &'a str, authorizer: &'a RefCell<dyn Authorizer>) -> Self {
130+
Self { email_address, authorizer }
131+
}
132+
}
133+
134+
impl PaymentProcessor for PaypalPaymentProcessor<'_> {
135+
fn pay(&self, order: &mut Order) {
136+
if !self.authorizer.borrow().is_authorized() {
137+
panic!("Not authorized");
138+
}
139+
140+
println!("Processing paypal payment type");
141+
println!("Using email address: {}", {self.email_address});
142+
order.status = "paid";
143+
}
144+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use std::cell::RefCell;
2+
3+
pub struct Order<'a> {
4+
pub items: Vec<&'a str>,
5+
pub quantities: Vec<u32>,
6+
pub prices: Vec<f32>,
7+
pub status: &'a str,
8+
}
9+
10+
impl<'a> Order<'a> {
11+
pub fn new() -> Self {
12+
Self { items: vec![], quantities: vec![], prices: vec![], status: "open" }
13+
}
14+
15+
pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) {
16+
self.items.push(name);
17+
self.quantities.push(quantity);
18+
self.prices.push(price);
19+
}
20+
21+
pub fn total_price(&self) -> f32 {
22+
let mut total: f32 = 0.0;
23+
24+
for (i, price) in self.prices.iter().enumerate() {
25+
total += self.quantities[i] as f32 * price;
26+
}
27+
28+
total
29+
}
30+
}
31+
32+
pub struct SMSAuthorizer {
33+
pub authorized: bool,
34+
}
35+
36+
impl SMSAuthorizer {
37+
pub fn new() -> Self {
38+
Self { authorized: false }
39+
}
40+
41+
pub fn verify_code(&mut self, code: u32) {
42+
println!("Verifying SMS code {code}");
43+
self.authorized = true;
44+
}
45+
46+
fn is_authorized(&self) -> bool {
47+
self.authorized
48+
}
49+
}
50+
51+
pub trait PaymentProcessor {
52+
fn pay(&self, order: &mut Order);
53+
}
54+
55+
pub struct DebitPaymentProcessor<'a> {
56+
pub security_code: &'a str,
57+
pub authorizer: &'a RefCell<SMSAuthorizer>,
58+
}
59+
60+
impl<'a> DebitPaymentProcessor<'a> {
61+
pub fn new(security_code: &'a str, authorizer: &'a RefCell<SMSAuthorizer>) -> Self {
62+
Self { security_code, authorizer }
63+
}
64+
}
65+
66+
impl PaymentProcessor for DebitPaymentProcessor<'_> {
67+
fn pay(&self, order: &mut Order) {
68+
if !self.authorizer.borrow().is_authorized() {
69+
panic!("Not authorized");
70+
}
71+
72+
println!("Processing debit payment type");
73+
println!("Verifying security code: {}", {self.security_code});
74+
order.status = "paid";
75+
}
76+
}
77+
78+
pub struct CreditPaymentProcessor<'a> {
79+
pub security_code: &'a str,
80+
}
81+
82+
impl<'a> CreditPaymentProcessor<'a> {
83+
pub fn new(security_code: &'a str) -> Self {
84+
Self { security_code }
85+
}
86+
}
87+
88+
impl PaymentProcessor for CreditPaymentProcessor<'_> {
89+
fn pay(&self, order: &mut Order) {
90+
println!("Processing credit payment type");
91+
println!("Verifying security code: {}", {self.security_code});
92+
order.status = "paid";
93+
}
94+
}
95+
96+
pub struct PaypalPaymentProcessor<'a> {
97+
pub email_address: &'a str,
98+
pub authorizer: &'a RefCell<SMSAuthorizer>,
99+
}
100+
101+
impl<'a> PaypalPaymentProcessor<'a> {
102+
pub fn new(email_address: &'a str, authorizer: &'a RefCell<SMSAuthorizer>) -> Self {
103+
Self { email_address, authorizer }
104+
}
105+
}
106+
107+
impl PaymentProcessor for PaypalPaymentProcessor<'_> {
108+
fn pay(&self, order: &mut Order) {
109+
if !self.authorizer.borrow().is_authorized() {
110+
panic!("Not authorized");
111+
}
112+
113+
println!("Processing paypal payment type");
114+
println!("Using email address: {}", {self.email_address});
115+
order.status = "paid";
116+
}
117+
}

better-rust/solid/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ pub mod open_closed_after;
55
pub mod liskov_substitution_before;
66
pub mod liskov_substitution_after;
77
pub mod interface_segregation_before;
8-
pub mod interface_segregation_after;
8+
pub mod interface_segregation_after;
9+
pub mod dependency_inversion_before;
10+
pub mod dependency_inversion_after;

better-rust/solid/src/main.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ fn main() {
1212
interface_segregation_before();
1313

1414
interface_segregation_after();
15+
16+
dependency_inversion();
1517
}
1618

1719
#[macros::example]
@@ -113,4 +115,25 @@ fn interface_segregation_after() {
113115
let processor = PaypalPaymentProcessor::new("[email protected]", &authorizer);
114116
authorizer.borrow_mut().verify_code(465839);
115117
processor.pay(&mut order);
118+
}
119+
120+
#[macros::example]
121+
fn dependency_inversion() {
122+
use solid::dependency_inversion_after::*;
123+
124+
let mut order = Order::new();
125+
126+
order.add_item("Keyboard", 1, 50.0);
127+
order.add_item("SSD", 1, 150.0);
128+
order.add_item("USB cable", 2, 5.0);
129+
130+
println!("{}", order.total_price());
131+
132+
// let authorizer = RefCell::new(SMSAuthorizer::new());
133+
let authorizer = RefCell::new(AuthorizerRobot::new());
134+
135+
let processor = PaypalPaymentProcessor::new("[email protected]", &authorizer);
136+
// authorizer.borrow_mut().verify_code(465839);
137+
authorizer.borrow_mut().not_a_robot();
138+
processor.pay(&mut order);
116139
}

0 commit comments

Comments
 (0)