1
+ //#30 - Principio SOLID de Inversión de Dependencias (Dependency Inversion Principle (DIP))
2
+ /*
3
+ * EJERCICIO:
4
+ * Explora el "Principio SOLID de Inversión de Dependencias (Dependency Inversion
5
+ * Principle, DIP)" y crea un ejemplo simple donde se muestre su funcionamiento
6
+ * de forma correcta e incorrecta.
7
+ *
8
+ * DIFICULTAD EXTRA (opcional):
9
+ * Crea un sistema de notificaciones.
10
+ * Requisitos:
11
+ * 1. El sistema puede enviar Email, PUSH y SMS (implementaciones específicas).
12
+ * 2. El sistema de notificaciones no puede depender de las implementaciones específicas.
13
+ * Instrucciones:
14
+ * 1. Crea la interfaz o clase abstracta.
15
+ * 2. Desarrolla las implementaciones específicas.
16
+ * 3. Crea el sistema de notificaciones usando el DIP.
17
+ * 4. Desarrolla un código que compruebe que se cumple el principio.
18
+ */
19
+ //Bibliografy: The Web Development Glossary (Jens Oliver Meiert) (Z-Library)
20
+ //GPT
21
+
22
+ /* Dependency Inversion Principle
23
+ A specific form of decoupling software modules. When following this
24
+ principle, the conventional dependency relationships established from
25
+ high-level policy-setting modules to low-level dependency modules are
26
+ reversed, thus rendering high-level modules independent of the low-level
27
+ module implementation details. The principle states 1) that high-level
28
+ modules should not depend on low-level modules, but that both should
29
+ depend on abstractions (e.g., interfaces), and 2) that abstractions should
30
+ not depend on details, but that details (concrete implementations) should
31
+ depend on abstractions.
32
+
33
+ A class that contains methods for use by other classes without having to be
34
+ the parent class of those other classes. How those other classes gain access
35
+ to the mixin’s methods depends on the language. Mixins are sometimes
36
+ described as being “included” rather than “inherited.” Mixins encourage
37
+ code reuse and can be used to avoid the inheritance ambiguity that
38
+ multiple inheritance can cause, or to work around lack of support for
39
+ multiple inheritance in a language. A mixin can also be viewed as an
40
+ interface with implemented methods. This pattern is an example of
41
+ enforcing the Dependency Inversion Principle */
42
+
43
+ let log = console . log ;
44
+
45
+ // Check if running in a browser environment
46
+ const isBrowser = typeof window !== 'undefined' ;
47
+
48
+ // Conditional check for browser environment
49
+ if ( isBrowser ) {
50
+ window . addEventListener ( 'load' , ( ) => {
51
+ const body : HTMLBodyElement | null = document . querySelector ( 'body' ) ;
52
+ const title = document . createElement ( 'h1' ) ;
53
+
54
+ body ?. style . setProperty ( 'background' , '#000' ) ;
55
+ body ?. style . setProperty ( 'text-align' , 'center' ) ;
56
+
57
+ title . textContent = 'Retosparaprogramadores #30.' ;
58
+ title . style . setProperty ( 'font-size' , '3.5vmax' ) ;
59
+ title . style . setProperty ( 'color' , '#fff' ) ;
60
+ title . style . setProperty ( 'line-height' , '100vh' ) ;
61
+
62
+ body ?. appendChild ( title ) ;
63
+
64
+ setTimeout ( ( ) => {
65
+ alert ( 'Retosparaprogramadores #30. Please open the Browser Developer Tools.' ) ;
66
+ } , 2000 ) ;
67
+ log ( 'Retosparaprogramadores #30' ) ;
68
+ } ) ;
69
+ } else {
70
+ log ( 'This code is designed to run in a browser environment. Skipping window-related code.' ) ;
71
+ log ( 'Retosparaprogramadores #30' ) ;
72
+ }
73
+
74
+ // Incorrect Example
75
+
76
+ class USABillingService1 {
77
+ calculateCharge ( duration : number ) : number {
78
+ return duration * 0.10 ; // $0.10 per minute
79
+ }
80
+ }
81
+
82
+ class CallBillingService1 {
83
+ public billingService : USABillingService1 ;
84
+
85
+ constructor ( ) {
86
+ this . billingService = new USABillingService1 ( ) ; // Direct dependency
87
+ }
88
+
89
+ billCall ( duration : number ) : void {
90
+ const charge = this . billingService . calculateCharge ( duration ) ;
91
+ log ( `Total charge: ${ charge . toFixed ( 2 ) } ` ) ;
92
+ }
93
+ }
94
+
95
+ const callBillingService1 = new CallBillingService1 ( ) ;
96
+ callBillingService1 . billCall ( 22 ) ; // Total charge: 2.20
97
+
98
+ // Correct Example
99
+
100
+ interface IBillingService {
101
+ calculateCharge ( duration : number ) : number ;
102
+ location : string ; // Add location property to the interface
103
+ }
104
+
105
+ class USABillingService implements IBillingService {
106
+ public location : string ;
107
+
108
+ constructor ( ) {
109
+ this . location = 'USA' ;
110
+ }
111
+
112
+ calculateCharge ( duration : number ) : number {
113
+ return duration * 0.10 ;
114
+ }
115
+ }
116
+
117
+ class EuropeBillingService implements IBillingService {
118
+ public location : string ;
119
+
120
+ constructor ( ) {
121
+ this . location = 'Europe' ;
122
+ }
123
+
124
+ calculateCharge ( duration : number ) : number {
125
+ return duration * 0.15 ;
126
+ }
127
+ }
128
+
129
+ class AsiaBillingService implements IBillingService {
130
+ public location : string ;
131
+
132
+ constructor ( ) {
133
+ this . location = 'Asia' ;
134
+ }
135
+
136
+ calculateCharge ( duration : number ) : number {
137
+ return duration * 0.05 ;
138
+ }
139
+ }
140
+
141
+ class CallBillingService {
142
+ public billingService : IBillingService ;
143
+
144
+ constructor ( billingService : IBillingService ) {
145
+ this . billingService = billingService ; // Dependency injection
146
+ }
147
+
148
+ billCall ( duration : number ) : void {
149
+ const charge = this . billingService . calculateCharge ( duration ) ;
150
+ log ( `Total charge for ${ this . billingService . location } : ${ charge . toFixed ( 2 ) } ` ) ;
151
+ }
152
+ }
153
+
154
+ const usaBillingService = new USABillingService ( ) ;
155
+ const europeBillingService = new EuropeBillingService ( ) ;
156
+ const asiaBillingService = new AsiaBillingService ( ) ;
157
+
158
+ const callBillingServiceUSA = new CallBillingService ( usaBillingService ) ;
159
+ const callBillingServiceEurope = new CallBillingService ( europeBillingService ) ;
160
+ const callBillingServiceAsia = new CallBillingService ( asiaBillingService ) ;
161
+
162
+ callBillingServiceUSA . billCall ( 127.22 ) ; // USA call Total charge: 12.72
163
+ callBillingServiceEurope . billCall ( 17.56 ) ; // Europe call Total charge: 2.63
164
+ callBillingServiceAsia . billCall ( 45.23 ) ; // Asia call Total charge: 2.26
0 commit comments