Skip to content

Commit 16e11d9

Browse files
authored
Merge pull request mouredev#4689 from blackriper/main
Reto#27-kotlin
2 parents 6c51a0e + e5b1ce6 commit 16e11d9

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
@file:Suppress("UNCHECKED_CAST")
2+
3+
import java.util.UUID
4+
import kotlin.math.pow
5+
6+
/*
7+
Open Closed Principle
8+
9+
Este principio establece que una entidad de software (clase, módulo, función, etc)
10+
debe quedar abierta para su extensión, pero cerrada para su modificación.
11+
12+
Con abierta para su extensión, nos quiere decir que una entidad de software debe tener la capacidad
13+
de adaptarse a los cambios y nuevas necesidades de una aplicación, pero con la segunda parte de “cerrada
14+
para su modificación” nos da a entender que la adaptabilidad de la entidad no debe darse
15+
como resultado de la modificación del core de dicha entidad si no como resultado de un diseño
16+
que facilite la extensión sin modificaciones.
17+
18+
*/
19+
20+
// ejemplo de lo que no debe hacerse
21+
22+
enum class AuthProviders{
23+
GOOGLE,
24+
FACEBOOK,
25+
GITHUB,
26+
APPLE
27+
}
28+
29+
data class UserData(val userID:UUID,var name:String)
30+
31+
32+
class AuthService{
33+
fun loginProvider(provider:AuthProviders):UserData{
34+
return when(provider){
35+
AuthProviders.GOOGLE-> signInWithGoogle()
36+
AuthProviders.FACEBOOK-> signInWithFacebook()
37+
AuthProviders.GITHUB-> signInWithGithub()
38+
AuthProviders.APPLE-> signInWithApple()
39+
}
40+
}
41+
42+
private fun signInWithGoogle():UserData{
43+
return UserData(UUID.randomUUID(),"Google User")
44+
}
45+
46+
private fun signInWithFacebook():UserData{
47+
return UserData(UUID.randomUUID(),"Facebook User")
48+
}
49+
50+
private fun signInWithGithub():UserData{
51+
return UserData(UUID.randomUUID(),"Github User")
52+
}
53+
54+
private fun signInWithApple():UserData{
55+
return UserData(UUID.randomUUID(),"Apple User")
56+
}
57+
}
58+
59+
/* El Principio SOLID Open Closed se suele resolver utilizando polimorfismo,
60+
clases abstractas, herencia y interfaces en el ejemplo usando herencia*/
61+
62+
open class AuthProvider{
63+
open fun login():UserData{
64+
return UserData(UUID.randomUUID(),"User")
65+
}
66+
}
67+
68+
// creamos los diferentes provedores
69+
class GoogleProvider:AuthProvider(){
70+
override fun login():UserData{
71+
return UserData(UUID.randomUUID(),"Google User")
72+
}
73+
}
74+
75+
class AppleProvider:AuthProvider(){
76+
override fun login():UserData{
77+
return UserData(UUID.randomUUID(),"Apple User")
78+
}
79+
}
80+
81+
// refactorizamos la clase autService
82+
class AuthProdService{
83+
fun loginProvider(provider:AuthProvider):UserData{
84+
return provider.login()
85+
}
86+
}
87+
// opcional crear singlenton
88+
object ProvidersSinglenton{
89+
val apple=AppleProvider()
90+
val google=GoogleProvider()
91+
92+
}
93+
94+
95+
96+
fun exampleOpenClosed(){
97+
val authService = AuthService()
98+
val userData = authService.loginProvider(AuthProviders.GOOGLE)
99+
println(userData)
100+
// usando principio
101+
val authProd=AuthProdService()
102+
val userApple=authProd.loginProvider(ProvidersSinglenton.apple)
103+
val useGoogle=authProd.loginProvider(ProvidersSinglenton.google)
104+
println(userApple)
105+
println(useGoogle)
106+
}
107+
108+
//ejercicio extra experimiento con genericos sustituir la T por el tipo que quieras
109+
interface Operation{
110+
fun<T> execute(num1:T,num2:T):T
111+
}
112+
//crear clases de las operaciones borrar los ifs y solo dejar la suma
113+
class Add:Operation{
114+
override fun <T> execute(num1: T, num2: T): T {
115+
if(num1 is Int && num2 is Int) return (num1+num2) as T
116+
if (num1 is Double && num2 is Double) return (num1+num2) as T
117+
if (num1 is Float && num2 is Float) return (num1+num2) as T
118+
if (num1 is Long && num2 is Long) return (num1+num2) as T
119+
throw Exception("calculate type not supported")
120+
}
121+
122+
}
123+
124+
class Rest:Operation {
125+
override fun <T> execute(num1: T, num2: T): T {
126+
if (num1 is Int && num2 is Int) return (num1 - num2) as T
127+
if (num1 is Double && num2 is Double) return (num1 - num2) as T
128+
if (num1 is Float && num2 is Float) return (num1 - num2) as T
129+
if (num1 is Long && num2 is Long) return (num1 - num2) as T
130+
throw Exception("calculate type not supported")
131+
}
132+
}
133+
134+
class Mul:Operation {
135+
override fun <T> execute(num1: T, num2: T): T {
136+
if (num1 is Int && num2 is Int) return (num1 * num2) as T
137+
if (num1 is Double && num2 is Double) return (num1 * num2) as T
138+
if (num1 is Float && num2 is Float) return (num1 * num2) as T
139+
if (num1 is Long && num2 is Long) return (num1 * num2) as T
140+
throw Exception("calculate type not supported")
141+
}
142+
}
143+
144+
class Div:Operation {
145+
override fun <T> execute(num1: T, num2: T): T {
146+
if (num1 is Int && num2 is Int) return (num1 / num2) as T
147+
if (num1 is Double && num2 is Double) return (num1 / num2) as T
148+
if (num1 is Float && num2 is Float) return (num1 / num2) as T
149+
if (num1 is Long && num2 is Long) return (num1 / num2) as T
150+
throw Exception("calculate type not supported")
151+
}
152+
}
153+
154+
class Calculate{
155+
fun <T>caculate(num1:T,num2:T,operation:Operation):T{
156+
if (num1 is Int && num2 is Int) return operation.execute(num1,num2)
157+
if (num1 is Double && num2 is Double) return operation.execute(num1,num2)
158+
if (num1 is Float && num2 is Float) return operation.execute(num1,num2)
159+
if (num1 is Long && num2 is Long) return operation.execute(num1,num2)
160+
throw Exception("calculate type not supported")
161+
}
162+
}
163+
164+
// se cumple el principio open closed porque la clase operation puede ser extendida pero la
165+
//clase calculate no puede ser extendida y no cambia su funcionamiento
166+
167+
class Pow:Operation{
168+
override fun <T> execute(num1: T, num2: T): T {
169+
if (num1 is Int && num2 is Int) return (num1.toDouble().pow(num2.toDouble())) as T
170+
if (num1 is Double && num2 is Double) return (num1.pow(num2)) as T
171+
if (num1 is Float && num2 is Float) return (num1.pow(num2)) as T
172+
if (num1 is Long && num2 is Long) return (num1.toFloat().pow(num2.toFloat())) as T
173+
throw Exception("calculate type not supported")
174+
}
175+
176+
}
177+
178+
179+
180+
// encapsular las operaciones en un singlenton para mayor comodidad opcional
181+
object OperationSingleton{
182+
val add=Add()
183+
val rest=Rest()
184+
val mul=Mul()
185+
val div=Div()
186+
val pow=Pow()
187+
}
188+
189+
fun calculatorExamples(){
190+
val calculator=Calculate()
191+
println("Add: "+calculator.caculate<Double>(2.5,2.5,OperationSingleton.add))
192+
println("Mul: "+calculator.caculate<Float>(2.5f,2.5f,OperationSingleton.mul))
193+
println("Div: "+calculator.caculate<Int>(2,2,OperationSingleton.div))
194+
println("Pow: "+calculator.caculate<Int>(2,2,OperationSingleton.pow))
195+
}
196+
197+
198+
199+
200+
fun main() {
201+
exampleOpenClosed()
202+
calculatorExamples()
203+
}
204+

0 commit comments

Comments
 (0)