-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSingleResponsibility.ts
More file actions
138 lines (122 loc) · 4.31 KB
/
Copy pathSingleResponsibility.ts
File metadata and controls
138 lines (122 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* SINGLE RESPONSIBILITY PRINCIPLE (SRP) - CORRECT IMPLEMENTATION
*
* SRP states: A class should have only ONE reason to change
* In other words, a class should have only ONE responsibility or job
*
* This file demonstrates the CORRECT way to follow SRP by separating concerns:
* - ShoppingCart: Manages products and calculations ONLY
* - ShoppingCartPrinter: Handles printing/display logic ONLY
* - ShoppingDBService: Handles database operations ONLY
*/
/**
* Product class - Simple data model
* Single responsibility: Represent a product with name and price
*/
class Product {
constructor(public name : string, public price : number){
}
}
/**
* ShoppingCart class - Focused on cart management
*
* Single Responsibility: Manage shopping cart items and calculations
*
* This class FOLLOWS SRP because:
* - It only manages products and calculates totals
* - Printing is delegated to ShoppingCartPrinter
* - Database operations are delegated to ShoppingDBService
*
* Note: The printInvoice() and saveToDB() methods still exist but are
* NOT the recommended way. Use ShoppingCartPrinter and ShoppingDBService instead.
*/
class ShoppingCart {
public products : Product[] = []
// Core responsibility: Managing products
public addProduct(product : Product){
this.products.push(product)
}
// Core responsibility: Calculating totals
public calculateTotalProduc() : number {
const total = this.products
.map(x => x.price)
.reduce((accumulator, currEle) => {
return accumulator + currEle
}, 0);
return total
}
// Exists for backward compatibility - prefer ShoppingCartPrinter
public printInvoice() : void {
const total = this.calculateTotalProduc()
console.log("Invoice Printed :", total);
}
// Exists for backward compatibility - prefer ShoppingDBService
public saveToDB(): void {
console.log("saving data to DB")
}
}
/**
* ShoppingCartPrinter - FOLLOWS SRP
*
* Single responsibility: Print/display shopping cart information
*
* Benefits:
* - If printing format changes (console, file, PDF), only this class changes
* - ShoppingCart doesn't need to know about printing details
* - Can be easily tested independently
* - Can be replaced with different printer implementations
*/
class ShoppingCartPrinter {
constructor(public cart : ShoppingCart){}
public printer() : void {
const total = this.cart.calculateTotalProduc();
console.log("Invoice Printed :", total);
}
}
/**
* ShoppingDBService - FOLLOWS SRP
*
* Single responsibility: Handle database persistence for shopping cart
*
* Benefits:
* - If database technology changes (SQL to NoSQL), only this class changes
* - ShoppingCart doesn't need to know about database details
* - Can be easily tested with mock databases
* - Can implement different storage strategies without affecting ShoppingCart
*/
class ShoppingDBService{
constructor(public cart : ShoppingCart){}
public saveCarToDb():void{
console.log("saving items", this.cart.products)
}
}
/**
* Usage example - CORRECT SRP implementation
*
* Each class has ONE clear responsibility:
* - ShoppingCart: Manages products and calculations
* - ShoppingCartPrinter: Handles printing/display
* - ShoppingDBService: Handles database persistence
*
* Benefits of following SRP:
* ✓ Easier to maintain (each class changes for only ONE reason)
* ✓ Easier to test (can test each class independently)
* ✓ More flexible (can change printing without touching cart logic)
* ✓ More reusable (printer works with any cart, not just this one)
* ✓ Better organization (clear separation of concerns)
*/
// Create products
const product1 = new Product("1", 1)
const product2 = new Product("2", 2)
const product3 = new Product("3", 3)
// ShoppingCart handles cart management only
const shoppingCart1 = new ShoppingCart()
shoppingCart1.addProduct(product1)
shoppingCart1.addProduct(product2)
shoppingCart1.addProduct(product3)
// ShoppingCartPrinter handles printing only (separation of concerns!)
const shopingcartPrinter = new ShoppingCartPrinter(shoppingCart1)
shopingcartPrinter.printer()
// ShoppingDBService handles database only (separation of concerns!)
const shoppingDBService = new ShoppingDBService(shoppingCart1)
shoppingDBService.saveCarToDb()