Skip to content

Commit e789507

Browse files
authored
Merge pull request mouredev#7197 from mrodara/mrodara/main
#29-Python
2 parents 72be212 + af75775 commit e789507

File tree

2 files changed

+352
-0
lines changed

2 files changed

+352
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
### Principio de Segregación de Interfaces (Interface Segregation Principle, ISP)
2+
3+
'''
4+
Este principio establece que:
5+
6+
"Ningún cliente debería depender de métodos que no utiliza."
7+
8+
Esto significa que las interfaces (o clases abstractas en Python) deben diseñarse de manera que los clientes que
9+
las implementan no se vean forzados a definir métodos innecesarios o irrelevantes.
10+
11+
Ventajas:
12+
13+
+ Reduce el acoplamiento
14+
+ Hace el código más modular
15+
+ Facilitan la implementación
16+
'''
17+
18+
# Ejemplo que viola el principio
19+
20+
from abc import ABC, abstractmethod
21+
22+
class Vehicle(ABC):
23+
24+
@abstractmethod
25+
def drive(self):
26+
pass
27+
28+
@abstractmethod
29+
def pilot(self):
30+
pass
31+
32+
@abstractmethod
33+
def navigate(self):
34+
pass
35+
36+
class Car(Vehicle):
37+
38+
def drive():
39+
print("El coche está en marcha")
40+
41+
def pilot(self):
42+
raise NotImplementedError("Un coche no puede volar")
43+
44+
def navigate(self):
45+
raise NotImplementedError("Un coche no puede navegar por el mar")
46+
47+
'''
48+
En este ejemplo los principales problemas son:
49+
- El cliente (Car) debe implementar métodos que no utiliza (pilot y navigate)
50+
- El cliente debe manejar excepciones innecesarias
51+
'''
52+
53+
# Fin Ejemplo que viola el principio
54+
55+
# Rediseño para no violar el ISP
56+
57+
class Driveable(ABC):
58+
59+
@abstractmethod
60+
def drive(self):
61+
pass
62+
63+
class Pilotable(ABC):
64+
65+
@abstractmethod
66+
def pilot(self):
67+
pass
68+
69+
class Navigateable(ABC):
70+
71+
@abstractmethod
72+
def navigate(self):
73+
pass
74+
75+
76+
class Car(Driveable):
77+
78+
def drive(self):
79+
print("El cocche está en marcha")
80+
81+
class Plane(Pilotable):
82+
83+
def pilot(self):
84+
print("El avión está volando")
85+
86+
class Ship(Navigateable):
87+
88+
def navigate(self):
89+
print("El barco se encuentra navegando en alta mar")
90+
91+
92+
# Fin Rediseño para no violar el ISP
93+
94+
## EJERCICIO EXTRA
95+
96+
class PrinterBW(ABC):
97+
98+
@abstractmethod
99+
def print_bn(self):
100+
pass
101+
102+
class PrinterColor(ABC):
103+
104+
@abstractmethod
105+
def print_color(self):
106+
pass
107+
108+
class Maileable(ABC):
109+
110+
@abstractmethod
111+
def send_mail(self):
112+
pass
113+
114+
class Faxeable(ABC):
115+
116+
@abstractmethod
117+
def send_fax(self):
118+
pass
119+
120+
class BwPrinter(PrinterBW):
121+
122+
def print_bn(self):
123+
print("Imprimiendo documento en Blanco/Negro")
124+
125+
class ColorPrinter(PrinterColor):
126+
127+
def print_color(self):
128+
print("Imprimiendo documento en Color")
129+
130+
class MultiFunction(PrinterBW, PrinterColor, Maileable, Faxeable):
131+
132+
def print_bn(self):
133+
print("Imprimiendo documento en Blanco/Negro")
134+
135+
def print_color(self):
136+
print("Imprimiendo documento en Color")
137+
138+
def send_mail(self, to="[email protected]", subject="Test", body="This is a mail test"):
139+
print(f"Enviando correo electrónico a {to} con asunto {subject} y mensaje {body}")
140+
141+
def send_fax(self, destination_number="+345557890", content="This is a fax test"):
142+
print(f"Enviando fax a {destination_number} con contenido {content}")
143+
144+
145+
# Batería de pruebas
146+
147+
def test_bw_printer():
148+
printer = BwPrinter()
149+
printer.print_bn() # Debería imprimir en blanco y negro
150+
151+
def test_color_printer():
152+
printer = ColorPrinter()
153+
printer.print_color() # Debería imprimir en color
154+
155+
def test_multi_function_print_bn():
156+
printer = MultiFunction()
157+
printer.print_bn() # Debería imprimir en blanco y negro
158+
159+
def test_multi_function_print_color():
160+
printer = MultiFunction()
161+
printer.print_color() # Debería imprimir en color
162+
163+
def test_multi_function_send_mail():
164+
printer = MultiFunction()
165+
printer.send_mail(to="[email protected]", subject="Prueba", body="Esto es una prueba")
166+
167+
def test_multi_function_send_fax():
168+
printer = MultiFunction()
169+
printer.send_fax(destination_number="+123456789", content="Esto es una prueba de fax")
170+
171+
def test_no_extra_methods_bw_printer():
172+
printer = BwPrinter()
173+
try:
174+
printer.print_color()
175+
except AttributeError:
176+
print("Error esperado: 'BwPrinter' no tiene método 'print_color'")
177+
178+
def test_no_extra_methods_color_printer():
179+
printer = ColorPrinter()
180+
try:
181+
printer.print_bn()
182+
except AttributeError:
183+
print("Error esperado: 'ColorPrinter' no tiene método 'print_bn'")
184+
185+
186+
print("Pruebas de BwPrinter:")
187+
test_bw_printer()
188+
test_no_extra_methods_bw_printer()
189+
190+
print("\nPruebas de ColorPrinter:")
191+
test_color_printer()
192+
test_no_extra_methods_color_printer()
193+
194+
print("\nPruebas de MultiFunction:")
195+
test_multi_function_print_bn()
196+
test_multi_function_print_color()
197+
test_multi_function_send_mail()
198+
test_multi_function_send_fax()
199+
200+
201+
## FIN EJERCICIO EXTRA
202+
203+
204+
205+
206+
207+
### FIN Principio de Segregación de Interfaces (Interface Segregation Principle, ISP)
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
### Principio de Inversión de Dependencias (Dependency Inversion Principle, DIP)
2+
3+
'''
4+
Este principio establece que:
5+
6+
Los módulos de alto nivel NO deben depender de los módulos de bajo nivel. Ambos deben depender de abstracciones.
7+
8+
Las abstracciones NO deben depender de los detalles. Los detalles DEBEN depender de las abstracciones.
9+
10+
En resumen, el DIP promueve que las clases principales (alto nivel) dependan de interfaces o abstracciones,
11+
en lugar de depender directamente de clases concretas (bajo nivel).
12+
'''
13+
14+
'''
15+
Ventajas:
16+
17+
+ Reduce el acoplamiento:
18+
Los módulos de alto nivel no dependen de los detalles específicos de implementación.
19+
+ Facilita el mantenimiento:
20+
Los detalles de implementación pueden cambiar sin afectar a las clases principales.
21+
+ Aumenta la flexibilidad y la extensibilidad:
22+
Es más sencillo sustituir o añadir implementaciones concretas al depender de abstracciones.
23+
24+
'''
25+
26+
# EJEMPLO QUE VIOLA EL PRINCIPIO
27+
28+
class CreditCardPayment():
29+
30+
def proccess_payment(self, amount):
31+
print(f"Procesando pago con tarjeta de crédito: {amount} €")
32+
33+
class OrderProccesor():
34+
35+
def __init__(self):
36+
self.payment_proccessor = CreditCardPayment()
37+
38+
def proccess_order(self, amount):
39+
self.payment_proccessor.proccess_payment(amount=amount)
40+
41+
'''
42+
Problemas detectados:
43+
44+
+ Dependencia directa:
45+
OrderProcessor está acoplada directamente a CreditCardPayment.
46+
No se puede usar otro método de pago sin modificar OrderProcessor.
47+
+ Falta de flexibilidad:
48+
Si necesitas añadir PayPalPayment o CryptoPayment, tendrás que modificar el código de OrderProcessor.
49+
'''
50+
51+
# FIN EJEMPLO QUE VIOLA EL PRINCIPIO
52+
53+
# REDISEÑO PARA CUMPLIR CON EL PRINCIPIO
54+
from abc import ABC, abstractmethod
55+
56+
class PaymentProccessor(ABC):
57+
58+
@abstractmethod
59+
def proccess_payment(self, amount):
60+
pass
61+
62+
class CreditCardPayment(PaymentProccessor):
63+
64+
def proccess_payment(self, amount):
65+
print(f"Procesando pago con tarjeta de crédito: {amount} €")
66+
67+
class PayPalPayment(PaymentProccessor):
68+
69+
def proccess_payment(self, amount):
70+
print(f"Procesando el pago mediante Paypal: {amount} €")
71+
72+
class BizumPayment(PaymentProccessor):
73+
74+
def proccess_payment(self, amount):
75+
print(f"Procesando el pago mediante Bizum: {amount} €")
76+
77+
78+
# Clase de Alto nivel
79+
class OrderProccessor():
80+
81+
def __init__(self, payment_proccessor):
82+
self.payment_proccessor = payment_proccessor
83+
84+
def proccess_order(self, amount):
85+
self.payment_proccessor.proccess_payment(amount=amount)
86+
87+
order = OrderProccessor(CreditCardPayment())
88+
order.proccess_order(amount=100)
89+
90+
order = OrderProccessor(PayPalPayment())
91+
order.proccess_order(amount=200)
92+
93+
order = OrderProccessor(BizumPayment())
94+
order.proccess_order(amount=300)
95+
96+
# FIN REDISEÑO PARA CUMPLIR CON EL PRINCIPIO
97+
98+
## EJERCICIO EXTRA
99+
100+
# CLASE ABSTRACTA
101+
class Notifier(ABC):
102+
103+
@abstractmethod
104+
def send_notification(self, message):
105+
pass
106+
107+
#Específicas
108+
class EmailNotifier(Notifier):
109+
110+
def send_notification(self, message):
111+
print(f"Enviando eamil con el mensaje {message}")
112+
113+
class PushNotifier(Notifier):
114+
115+
def send_notification(self, message):
116+
print(f"Enviando mensaje Push con texto: {message}")
117+
118+
class SmsNotifier(Notifier):
119+
def send_notification(self, message):
120+
print(f"Enviando mensaje SMS con texto: {message}")
121+
122+
# Alto nivel
123+
class NotificationSender():
124+
125+
def __init__(self, notifier: Notifier):
126+
self.notifier = notifier
127+
128+
def send_notification(self, message):
129+
self.notifier.send_notification(message)
130+
131+
132+
# Batería de pruebas
133+
email_sender = NotificationSender(EmailNotifier())
134+
email_sender.send_notification("Hola soy un Email")
135+
136+
push_sender = NotificationSender(PushNotifier())
137+
push_sender.send_notification("Hola soy un Push")
138+
139+
sms_sender = NotificationSender(SmsNotifier())
140+
sms_sender.send_notification("Hola soy un SMS")
141+
142+
143+
## FIN EJERCICIO EXTRA
144+
145+
### FIN Principio de Inversión de Dependencias (Dependency Inversion Principle, DIP)

0 commit comments

Comments
 (0)