Skip to content

Commit 4399295

Browse files
authored
Merge pull request #8224 from ignaciovihe/ejercicio-23
#23 - Python
2 parents 9443ae7 + 9471f7a commit 4399295

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
"""
2+
* EJERCICIO:
3+
* Explora el patrón de diseño "singleton" y muestra cómo crearlo
4+
* con un ejemplo genérico.
5+
"""
6+
7+
class Singleton:
8+
_instance = None # Aqui se guarda la instancia. Sera unica y todos los que intenten crear un Singleton se les devolvera esta.
9+
10+
def __new__(cls): # Se ejecuta antes de init.
11+
if cls._instance == None: # Si la instancia no esta creada.
12+
cls._instance = super(Singleton, cls).__new__(cls) # Lo creo usando en metodo new de su clase superior y pasandole cls
13+
return cls._instance # Devuelvo la instancia. Siempre la misma.
14+
15+
a = Singleton()
16+
print(a)
17+
b = Singleton()
18+
print(b)
19+
print(a is b)
20+
21+
22+
"""
23+
* DIFICULTAD EXTRA (opcional):
24+
* Utiliza el patrón de diseño "singleton" para representar una clase que
25+
* haga referencia a la sesión de usuario de una aplicación ficticia.
26+
* La sesión debe permitir asignar un usuario (id, username, nombre y email),
27+
* recuperar los datos del usuario y borrar los datos de la sesión.
28+
"""
29+
# Version simple con una sola clase. Si queremos hacer otras clases singleton deberemos modificar su metodo new en cada una
30+
class UserSession():
31+
_instance = None
32+
33+
def __new__(cls):
34+
if cls._instance == None:
35+
cls._instance = super(UserSession, cls).__new__(cls)
36+
cls._instance.user = None # Se crea un atributo de instacia desde new para no usar init cada vez y tener que controlar la inicialización con un flag.
37+
return cls._instance
38+
39+
def set_user(self, id, username, name, email):
40+
self.user = {
41+
"id": id,
42+
"username": username,
43+
"name": name,
44+
"email": email
45+
}
46+
47+
def get_user_data(self):
48+
if self.user:
49+
return f"{self.user["id"]} - {self.user["username"]} - {self.user["name"]} - {self.user["email"]}"
50+
else:
51+
print("Sesión sin usuario")
52+
53+
def delete_session(self):
54+
self.user = None
55+
56+
print("------------------con clase simple-------------------------")
57+
session1 = UserSession()
58+
print(session1.get_user_data())
59+
session1.set_user(1, "culiembres", "ignacio", "email@email.com")
60+
print(session1.get_user_data())
61+
62+
session2 = UserSession()
63+
print(session2.get_user_data())
64+
65+
session3 = UserSession()
66+
session3.set_user(2, "pepeluis", "Pepe", "mielamil@email.com")
67+
print(session3.get_user_data())
68+
69+
session3.delete_session()
70+
session3.get_user_data()
71+
72+
73+
# Version con metaclase para varias clases singleton. Siguiento las indicaciones de https://refactoring.guru/
74+
75+
class SingletonMeta(type): # Se utiliza una metaclase para modificar el comportamiento de call
76+
# Todas las clases tienen la metaclase type por defecto
77+
_instances = {} # Se crea un dict para guardas las instacias unicas de las clases que queremos que sean singleton.
78+
79+
def __call__(cls, *args, **kwds):
80+
81+
if cls not in cls._instances:
82+
instance = super().__call__(*args, **kwds) # Creamos la instancia llamando al metodo call de type(metaclase base)
83+
cls._instances[cls] = instance # internamente type.call llama a los metodos new y init de las clases(ej:UsserConnection, BBDDconnection)
84+
return cls._instances[cls]
85+
86+
87+
class UserConnection(metaclass=SingletonMeta): # Le indicamos que la calse tiene una metaclase definida opor nosotros(por defecto seria type)
88+
89+
def __init__(self):
90+
self.user = None
91+
92+
def set_user(self, id, username, name, email):
93+
self.user = {
94+
"id": id,
95+
"username": username,
96+
"name": name,
97+
"email": email
98+
}
99+
100+
def get_user_data(self):
101+
if self.user:
102+
return f"{self.user['id']} - {self.user['username']} - {self.user['name']} - {self.user['email']}"
103+
else:
104+
return "Sesión sin usuario"
105+
106+
def delete_session(self):
107+
self.user = None
108+
109+
110+
class BBDDConnection(metaclass=SingletonMeta):
111+
112+
def __init__(self):
113+
self.bbdd = {
114+
"name": "Pedro",
115+
"edad": 35
116+
}
117+
118+
def get_data(self):
119+
return self.bbdd
120+
121+
122+
123+
print("------------------con metaclass------------------------")
124+
125+
connection1 = UserConnection()
126+
connection1.set_user(1, "pepito", "Pepe", "pepe@email.com")
127+
print(connection1.get_user_data())
128+
129+
connection2 = UserConnection()
130+
print(connection2.get_user_data())
131+
132+
print(connection1 is connection2)
133+
134+
bbddc1 = BBDDConnection()
135+
print(bbddc1.get_data())
136+
137+
bbddc2 = BBDDConnection()
138+
print(bbddc2.get_data())
139+
140+
print(bbddc1 is bbddc2)
141+
142+

0 commit comments

Comments
 (0)