Skip to content

Commit 6e2aaa1

Browse files
committed
Add interface segregation
1 parent d64bd27 commit 6e2aaa1

File tree

4 files changed

+266
-0
lines changed

4 files changed

+266
-0
lines changed
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+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
2+
pub struct Order<'a> {
3+
pub items: Vec<&'a str>,
4+
pub quantities: Vec<u32>,
5+
pub prices: Vec<f32>,
6+
pub status: &'a str,
7+
}
8+
9+
impl<'a> Order<'a> {
10+
pub fn new() -> Self {
11+
Self { items: vec![], quantities: vec![], prices: vec![], status: "open" }
12+
}
13+
14+
pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) {
15+
self.items.push(name);
16+
self.quantities.push(quantity);
17+
self.prices.push(price);
18+
}
19+
20+
pub fn total_price(&self) -> f32 {
21+
let mut total: f32 = 0.0;
22+
23+
for (i, price) in self.prices.iter().enumerate() {
24+
total += self.quantities[i] as f32 * price;
25+
}
26+
27+
total
28+
}
29+
}
30+
31+
pub trait PaymentProcessor {
32+
fn auth_sms(&mut self, code: u32);
33+
34+
fn pay(&self, order: &mut Order);
35+
}
36+
37+
pub struct DebitPaymentProcessor<'a> {
38+
pub security_code: &'a str,
39+
pub verified: bool,
40+
}
41+
42+
impl<'a> DebitPaymentProcessor<'a> {
43+
pub fn new(security_code: &'a str) -> Self {
44+
Self { security_code, verified: false }
45+
}
46+
}
47+
48+
impl PaymentProcessor for DebitPaymentProcessor<'_> {
49+
fn auth_sms(&mut self, code: u32) {
50+
println!("Verifying SMS code {code}");
51+
self.verified = true;
52+
}
53+
54+
fn pay(&self, order: &mut Order) {
55+
println!("Processing debit payment type");
56+
println!("Verifying security code: {}", {self.security_code});
57+
order.status = "paid";
58+
}
59+
}
60+
61+
pub struct CreditPaymentProcessor<'a> {
62+
pub security_code: &'a str,
63+
}
64+
65+
impl<'a> CreditPaymentProcessor<'a> {
66+
pub fn new(security_code: &'a str) -> Self {
67+
Self { security_code }
68+
}
69+
}
70+
71+
impl PaymentProcessor for CreditPaymentProcessor<'_> {
72+
fn auth_sms(&mut self, _code: u32) {
73+
panic!("Credit card payments don't support SMS code authorization.");
74+
}
75+
76+
fn pay(&self, order: &mut Order) {
77+
println!("Processing credit payment type");
78+
println!("Verifying security code: {}", {self.security_code});
79+
order.status = "paid";
80+
}
81+
}
82+
83+
pub struct PaypalPaymentProcessor<'a> {
84+
pub email_address: &'a str,
85+
pub verified: bool,
86+
}
87+
88+
impl<'a> PaypalPaymentProcessor<'a> {
89+
pub fn new(email_address: &'a str) -> Self {
90+
Self { email_address, verified: false }
91+
}
92+
}
93+
94+
impl PaymentProcessor for PaypalPaymentProcessor<'_> {
95+
fn auth_sms(&mut self, code: u32) {
96+
println!("Verifying SMS code {code}");
97+
self.verified = true;
98+
}
99+
100+
fn pay(&self, order: &mut Order) {
101+
println!("Processing paypal payment type");
102+
println!("Using email address: {}", {self.email_address});
103+
order.status = "paid";
104+
}
105+
}

better-rust/solid/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ pub mod open_closed_before;
44
pub mod open_closed_after;
55
pub mod liskov_substitution_before;
66
pub mod liskov_substitution_after;
7+
pub mod interface_segregation_before;
8+
pub mod interface_segregation_after;

better-rust/solid/src/main.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::cell::RefCell;
2+
13
fn main() {
24
single_responsibility_before();
35

@@ -6,6 +8,10 @@ fn main() {
68
open_closed();
79

810
liskov_substitution();
11+
12+
interface_segregation_before();
13+
14+
interface_segregation_after();
915
}
1016

1117
#[macros::example]
@@ -70,5 +76,41 @@ fn liskov_substitution() {
7076

7177
let processor = PaypalPaymentProcessor::new("[email protected]");
7278

79+
processor.pay(&mut order);
80+
}
81+
82+
#[macros::example]
83+
fn interface_segregation_before() {
84+
use solid::interface_segregation_before::*;
85+
86+
let mut order = Order::new();
87+
88+
order.add_item("Keyboard", 1, 50.0);
89+
order.add_item("SSD", 1, 150.0);
90+
order.add_item("USB cable", 2, 5.0);
91+
92+
println!("{}", order.total_price());
93+
94+
let mut processor = DebitPaymentProcessor::new("2349875");
95+
processor.auth_sms(465839);
96+
processor.pay(&mut order);
97+
}
98+
99+
#[macros::example]
100+
fn interface_segregation_after() {
101+
use solid::interface_segregation_after::*;
102+
103+
let mut order = Order::new();
104+
105+
order.add_item("Keyboard", 1, 50.0);
106+
order.add_item("SSD", 1, 150.0);
107+
order.add_item("USB cable", 2, 5.0);
108+
109+
println!("{}", order.total_price());
110+
111+
let authorizer = RefCell::new(SMSAuthorizer::new());
112+
113+
let processor = PaypalPaymentProcessor::new("[email protected]", &authorizer);
114+
authorizer.borrow_mut().verify_code(465839);
73115
processor.pay(&mut order);
74116
}

0 commit comments

Comments
 (0)