Skip to content

Commit a3b0bdb

Browse files
Merge branch 'main' of github.com:mouredev/roadmap-retos-programacion into JesusAEE
2 parents 7067533 + 3d75efd commit a3b0bdb

File tree

4 files changed

+908
-331
lines changed

4 files changed

+908
-331
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
Interface Segregation Principle
3+
4+
Este principio nos dice que una clase nunca debe extender de interfaces con métodos que no usa,
5+
por el principio de segregación de interfaces busca que las interfaces sean lo más pequeñas
6+
y específicas posible de modo que cada clase solo implemente los métodos que necesita.
7+
8+
errores comunes con este principio
9+
10+
- Estaremos violando este principio si Tenemos clases que implementan métodos de interfaces que no se usan.
11+
12+
- Definimos interfaces con parámetros que no se van a utilizar en todas las clases
13+
14+
-cuando tenemos interfaces muy grandes y métodos que no son genéricos y que otras clases que implementen esta interfaz no puedan usar
15+
16+
*/
17+
18+
//ejemplo de lo que no debe de hacerce
19+
20+
21+
interface Bank {
22+
fun deposit(amount: Double)
23+
fun withdraw(amount: Double)
24+
fun getBalance()
25+
}
26+
27+
class AccountNormal(private var balance: Double):Bank{
28+
override fun deposit(amount: Double) {
29+
balance+=amount
30+
}
31+
32+
override fun withdraw(amount: Double) {
33+
balance-=amount
34+
}
35+
36+
override fun getBalance() {
37+
println("the balance is $balance")
38+
}
39+
40+
}
41+
// esta cuenta solo es de imversion y esta no pueda hacer retiros por lo tanto rompe este principio
42+
// porque solo retornamos el error
43+
class InterestAccount(private var balance: Double):Bank {
44+
override fun deposit(amount: Double) {
45+
balance += amount
46+
}
47+
48+
override fun withdraw(amount: Double) {
49+
throw Exception("not allowed this operation")
50+
}
51+
52+
override fun getBalance() {
53+
println("the balance is $balance")
54+
}
55+
}
56+
57+
// lo que debe de hacerce
58+
59+
// quitamos el metodo que solo se permite en las dos clases
60+
interface LspBank{
61+
fun deposit(amount: Double)
62+
fun getBalance()
63+
}
64+
//las inferfaces pueden extender de otras interfaces ahora este inferfaz hija herera los metodos del padre
65+
// pero agrega la fucnionalidad de withdraw
66+
interface LspNormalBank : LspBank{
67+
fun withdraw(amount: Double)
68+
}
69+
70+
class NormalAccountLsp(private var balance: Double):LspNormalBank {
71+
override fun withdraw(amount: Double) {
72+
balance -= amount
73+
}
74+
75+
override fun deposit(amount: Double) {
76+
balance += amount
77+
}
78+
79+
override fun getBalance() {
80+
println("the balance is $balance")
81+
}
82+
}
83+
84+
class InterestAccountLsp(private var balance: Double):LspBank {
85+
override fun deposit(amount: Double) {
86+
balance += amount
87+
}
88+
89+
override fun getBalance() {
90+
println("the balance is $balance")
91+
}
92+
}
93+
94+
fun exmapleLsp(){
95+
val normal = NormalAccountLsp(100.0)
96+
normal.deposit(100.0)
97+
normal.getBalance()
98+
normal.withdraw(50.0)
99+
normal.getBalance()
100+
101+
val inv = InterestAccountLsp(100.0)
102+
inv.deposit(100.0)
103+
inv.getBalance()
104+
105+
println("violation this principle")
106+
// clase que viola esta principio
107+
val interest = InterestAccount(100.0)
108+
interest.deposit(100.0)
109+
interest.getBalance()
110+
// me veo forzado a chacar el error
111+
runCatching { interest.withdraw(50.0)}.let { println(it.exceptionOrNull()?.message) }
112+
interest.getBalance()
113+
}
114+
115+
//ejercicio extra
116+
117+
enum class ColorPrint{
118+
BLACK_AND_WHITE,
119+
COLOR
120+
}
121+
122+
interface Printer{
123+
fun print(document:String)
124+
}
125+
126+
// aplicando el principio de ISP para crear una nueva interfaz cuando esta tenga multiples funciones
127+
interface MultiFunctionPrinter : Printer{
128+
fun sendFax(document:String):Boolean
129+
fun scan(document:String)
130+
}
131+
132+
class NormalPrinter(val color:ColorPrint):Printer{
133+
override fun print(document: String) {
134+
println("Printing $document in color: $color")
135+
}
136+
137+
}
138+
139+
class MultiFuncPrinter(val color:ColorPrint):MultiFunctionPrinter {
140+
override fun sendFax(document: String): Boolean {
141+
if (document.isNotEmpty()){
142+
println("Sending $document by fax")
143+
return true
144+
}
145+
return false
146+
}
147+
148+
override fun scan(document: String) {
149+
document.isNotEmpty().run {
150+
println("Scanning $document")
151+
}
152+
}
153+
154+
override fun print(document: String) {
155+
println("Printing $document in color: $color")
156+
}
157+
}
158+
159+
fun pritingDocument(printer:Printer, document:String){
160+
printer.print(document)
161+
}
162+
163+
fun examplePrinter(){
164+
val normalPrinter = NormalPrinter(ColorPrint.BLACK_AND_WHITE)
165+
pritingDocument(normalPrinter,"Hello World")
166+
val multiFuncPrinter = MultiFuncPrinter(ColorPrint.COLOR)
167+
pritingDocument(multiFuncPrinter,"Kotlin is son of Java")
168+
multiFuncPrinter.sendFax("Hello Comunity")
169+
multiFuncPrinter.scan("Hello World")
170+
}
171+
172+
173+
fun main() {
174+
exmapleLsp()
175+
examplePrinter()
176+
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
(******************************************************************************)
2+
(* *)
3+
(* Interface Segregation Principle *)
4+
(* *)
5+
(* The core concept of this principle (the 'I' in {b SOLID}) is, a class *)
6+
(* should not be forced to implement methods that it doesn't need, caused *)
7+
(* by the implementation of a broad interface, or inheriting from a general *)
8+
(* abstract class that covers more ground than it should. *)
9+
(* *)
10+
(* The proposed solution is to create smaller interfaces that are only im- *)
11+
(* plemented if the class needs those methods and/or members and only *)
12+
(* inherit from a base class that won't force unwanted implementations. It *)
13+
(* goes hand in hand with the Liskov-Substitution Principle as it helps *)
14+
(* reduce the amount of exceptions thrown. *)
15+
(* *)
16+
(******************************************************************************)
17+
18+
open Printf
19+
20+
(* This interface violates the ISP because if implemented by a specific type of
21+
coffee machine, it will be forced to implement methods that it doesn't need
22+
and thus it'll need to either throw an exception or provide a NoOP body. *)
23+
class type coffee_machine_violating_isp = object
24+
method drip_brew : unit
25+
method replace_filter : unit
26+
method steam_milk : unit
27+
method pressure_brew : unit
28+
method add_ground_coffee : unit
29+
end
30+
31+
class type coffee_machine = object
32+
method brew : unit
33+
method add_ground_coffee : unit
34+
end
35+
36+
class type drip = object
37+
(* Inheriting a class type from another class type in OCaml is the same
38+
as extending an interface in OOP languages. Though we can't implement
39+
multiple interfaces, we can in fact inherit from multiple classes! *)
40+
inherit coffee_machine
41+
method drip_brew : unit
42+
method replace_filter : unit
43+
end
44+
45+
class type espresso = object
46+
inherit coffee_machine
47+
method steam_milk : unit
48+
method pressure_brew : unit
49+
end
50+
51+
class drip_machine : drip =
52+
object (self)
53+
method private drip_brew = print_endline "Brewing through a paper filter..."
54+
55+
method add_ground_coffee =
56+
print_endline "Adding ground coffee to drip coffee machine..."
57+
58+
method replace_filter = print_endline "Replacing paper filter..."
59+
method brew = self#drip_brew
60+
end
61+
62+
class espresso_machine : espresso =
63+
object (self)
64+
method private pressure_brew =
65+
print_endline "Brewing through an espresso portafilter..."
66+
67+
method add_ground_coffee =
68+
print_endline
69+
"Adding and compressing ground coffee to espresso machine..."
70+
71+
method steam_milk = print_endline "Steaming milk for latte art..."
72+
method brew = self#pressure_brew
73+
end
74+
75+
let _ =
76+
let oster_drip : drip_machine = new drip_machine in
77+
let barista : espresso_machine = new espresso_machine in
78+
oster_drip#add_ground_coffee;
79+
oster_drip#brew;
80+
oster_drip#replace_filter;
81+
barista#add_ground_coffee;
82+
barista#brew;
83+
barista#steam_milk
84+
;;
85+
86+
(******************************************************************************)
87+
(* *)
88+
(* Dificultad Extra (Opcional) *)
89+
(* *)
90+
(* Crea un gestor de impresoras. *)
91+
(* Requisitos: *)
92+
(* 1. Algunas impresoras solo imprimen en blanco y negro. *)
93+
(* 2. Otras solo a color. *)
94+
(* 3. Otras son multifunción, pueden imprimir, escanear y enviar fax. *)
95+
(* Instrucciones: *)
96+
(* 1. Implementan el sistema, con los diferentes tipos de impresoras y fun- *)
97+
(* ciones. *)
98+
(* 2. Aplica el ISP a la implementación. *)
99+
(* 3. Desarrolla un código que compruebe que se cumple el principio. *)
100+
(* *)
101+
(******************************************************************************)
102+
103+
class virtual black_white_printing =
104+
object
105+
method virtual print_b_and_w : string -> unit
106+
end
107+
108+
class virtual color_printing =
109+
object
110+
method virtual print_color : string -> unit
111+
end
112+
113+
class virtual fax (number : string) =
114+
object
115+
val phone_number = number
116+
method virtual send_document : string -> string -> unit
117+
end
118+
119+
class virtual scanner =
120+
object
121+
method virtual scan_document : string -> unit
122+
end
123+
124+
class bw_printer =
125+
object
126+
inherit black_white_printing
127+
128+
method print_b_and_w docfile =
129+
printf "Printing [%s] in black and white...\n" docfile
130+
end
131+
132+
class color_printer =
133+
object
134+
inherit color_printing
135+
136+
method print_color docfile =
137+
printf "Printing [%s] in CYMK color...\n" docfile
138+
end
139+
140+
class multifunctional_printer (number : string) =
141+
object (self)
142+
(* As I mentioned before, OCaml's class system offers multiple inheritance
143+
but I could have also made them interfaces (class types) and in order to
144+
create an interface that 'implements' all of them we could have done:
145+
146+
{[
147+
class multifunctional_printer (number : string) : object
148+
inherit color_printing
149+
inherit black_white_printing
150+
inherit scanner
151+
inherit fax
152+
end = object (self) end
153+
]}
154+
155+
This way we'd be forced to implement all of those methods but with one
156+
catch: using class types 'seals' a class, meaning we can't expose more
157+
public methods other than the ones in the interface.
158+
*)
159+
inherit color_printing
160+
inherit black_white_printing
161+
inherit scanner
162+
inherit fax number
163+
164+
method scan_document docfile =
165+
printf "Scanning [%s] with a multifunctional\n" docfile
166+
167+
method send_document docfile destination_number =
168+
printf
169+
"Sending [%s] from #%s to fax #%s through a multifunctional\n"
170+
docfile
171+
phone_number
172+
destination_number
173+
174+
method private print_b_and_w docfile =
175+
printf
176+
"Printing [%s] in black and white using a multifunctional\n"
177+
docfile
178+
179+
method private print_color docfile =
180+
printf "Printing [%s] in CYMK color using a multifunctional\n" docfile
181+
182+
method print ?(use_color = true) docfile =
183+
if use_color then self#print_color docfile else self#print_b_and_w docfile
184+
end
185+
186+
let _ =
187+
let compaq_bw = new bw_printer in
188+
let epson_color = new color_printer in
189+
let epson_mf = new multifunctional_printer "664-934-1295" in
190+
compaq_bw#print_b_and_w "2024report.xlsx";
191+
epson_color#print_color "wedding_album.pdf";
192+
epson_mf#print ~use_color:false "essat.docx";
193+
epson_mf#send_document "private_letter.txt" "55-676-2424";
194+
epson_mf#scan_document "ocr_test.jpg"
195+
;;

0 commit comments

Comments
 (0)