Skip to content

Commit 0984bec

Browse files
authored
Enhance readme with Singleton pattern refactoring guide
Added detailed instructions and code examples for refactoring a coffee shop order system using the Singleton pattern, including real-world scenarios, activities, and code smells.
1 parent b92af3f commit 0984bec

File tree

1 file changed

+176
-1
lines changed

1 file changed

+176
-1
lines changed
Lines changed: 176 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,176 @@
1-
.
1+
2+
3+
## ☕ Práctica: Refactorización con Singleton en una Cafetería
4+
5+
### 🔍 Escenario del Mundo Real
6+
7+
La cafetería "Café Singleton" tiene un sistema interno que utiliza una clase para llevar el **registro central de pedidos del día**. Sin embargo, cada vez que un barista toma un pedido, se crea una nueva instancia de `RegistroPedidos`, provocando inconsistencias y pérdidas de información.
8+
9+
### 🎯 Objetivo
10+
11+
Identificar los problemas en el diseño y aplicar el patrón **Singleton** para que toda la cafetería use la **misma instancia compartida del registro de pedidos**.
12+
13+
---
14+
15+
### 🧩 Categoría del patrón: **Creacional**
16+
17+
El patrón **Singleton** pertenece a los patrones **Creacionales**, ya que su objetivo es **controlar la instancia** de un objeto que solo debe existir **una vez en toda la aplicación**.
18+
19+
---
20+
21+
### 📋 Actividades
22+
23+
1. **Detecta los Code Smells** en el diseño inicial:
24+
25+
* ¿Cuántas instancias se crean?
26+
* ¿Hay duplicidad de pedidos?
27+
* ¿Hay acoplamiento innecesario?
28+
29+
2. **Refactoriza aplicando el patrón Singleton:**
30+
31+
* Asegura que `RegistroPedidos` tenga **una sola instancia global y segura**.
32+
* Implementa la **versión thread-safe** para evitar errores en concurrencia.
33+
34+
3. **Evalúa ventajas y riesgos del Singleton en este caso:**
35+
36+
* ¿Podrías testear esta clase?
37+
* ¿Qué pasaría si decides reiniciar el conteo de pedidos?
38+
39+
---
40+
41+
### 🧪 Sugerencias de patrones complementarios:
42+
43+
* **Observer**: si quieres notificar a otros módulos cuando se agrega un pedido.
44+
* **Command**: si cada pedido se representa como un comando a ejecutar.
45+
* **Memento**: si quieres guardar el estado del registro a intervalos.
46+
47+
---
48+
49+
### 🧾 Ansible Playbook de la práctica
50+
51+
```yaml
52+
---
53+
- name: Instalar .NET 8 y desplegar simulador de cafetería con Singleton
54+
hosts: localhost
55+
become: yes
56+
tasks:
57+
- name: Instalar dotnet-sdk-8.0
58+
apt:
59+
name: dotnet-sdk-8.0
60+
state: present
61+
62+
- name: Crear carpeta de la práctica
63+
file:
64+
path: /home/ubuntu/cafeteria_singleton
65+
state: directory
66+
67+
- name: Crear proyecto
68+
command: dotnet new console -n CafeteriaSingleton
69+
args:
70+
chdir: /home/ubuntu/cafeteria_singleton
71+
72+
- name: Copiar código con errores de diseño
73+
copy:
74+
dest: /home/ubuntu/cafeteria_singleton/CafeteriaSingleton/Program.cs
75+
content: |
76+
// Código con múltiples instancias de RegistroPedidos
77+
// TU MISIÓN: Detectar, refactorizar, aplicar Singleton
78+
79+
- name: Ejecutar el código para observar problemas
80+
command: dotnet run
81+
args:
82+
chdir: /home/ubuntu/cafeteria_singleton/CafeteriaSingleton
83+
```
84+
85+
---
86+
87+
☕ Código inicial con errores (sin Singleton)
88+
89+
Aquí tienes el **código inicial defectuoso** del sistema de pedidos de una cafetería. Está **intencionalmente mal diseñado** para que puedas **practicar la refactorización aplicando el patrón Singleton**.
90+
91+
---
92+
93+
## ☕ Código inicial con errores (sin Singleton)
94+
95+
📁 **Ubicación sugerida:** `/home/ubuntu/cafeteria_singleton/CafeteriaSingleton/Program.cs`
96+
97+
```csharp
98+
using System;
99+
using System.Collections.Generic;
100+
101+
namespace CafeteriaSingleton
102+
{
103+
public class Pedido
104+
{
105+
public string Cliente { get; set; }
106+
public string Bebida { get; set; }
107+
108+
public Pedido(string cliente, string bebida)
109+
{
110+
Cliente = cliente;
111+
Bebida = bebida;
112+
}
113+
}
114+
115+
// ❌ Esta clase se instancia cada vez, perdiendo el control central
116+
public class RegistroPedidos
117+
{
118+
private List<Pedido> pedidos = new List<Pedido>();
119+
120+
public void AgregarPedido(Pedido pedido)
121+
{
122+
pedidos.Add(pedido);
123+
Console.WriteLine($"📝 Pedido agregado: {pedido.Cliente} - {pedido.Bebida}");
124+
}
125+
126+
public void MostrarPedidos()
127+
{
128+
Console.WriteLine("📋 Pedidos registrados:");
129+
foreach (var pedido in pedidos)
130+
{
131+
Console.WriteLine($"- {pedido.Cliente}: {pedido.Bebida}");
132+
}
133+
}
134+
}
135+
136+
class Program
137+
{
138+
static void Main(string[] args)
139+
{
140+
// ☠️ Cada barista crea su propio registro
141+
var registroBarista1 = new RegistroPedidos();
142+
registroBarista1.AgregarPedido(new Pedido("Ana", "Latte"));
143+
144+
var registroBarista2 = new RegistroPedidos();
145+
registroBarista2.AgregarPedido(new Pedido("Luis", "Café Americano"));
146+
147+
// ❌ No se ven todos los pedidos, cada uno tiene su propia lista
148+
Console.WriteLine("\nRegistro del barista 1:");
149+
registroBarista1.MostrarPedidos();
150+
151+
Console.WriteLine("\nRegistro del barista 2:");
152+
registroBarista2.MostrarPedidos();
153+
154+
Console.WriteLine("\n¿Dónde está la lista completa? 🤔");
155+
}
156+
}
157+
}
158+
```
159+
160+
---
161+
162+
### 🚨 Code Smells Detectados
163+
164+
* Se crean múltiples instancias de `RegistroPedidos`.
165+
* No hay un punto de acceso único ni control de concurrencia.
166+
* El estado de los pedidos **no se comparte** entre baristas.
167+
* Violación del principio **Single Source of Truth**.
168+
169+
---
170+
171+
### 🧠 Desafío
172+
173+
Refactoriza `RegistroPedidos` aplicando el patrón **Singleton (versión thread-safe con lazy initialization)** para que **todos los baristas usen la misma instancia compartida**.
174+
175+
¿Listo para intentarlo?
176+
¿Quieres que también te sugiera pasos guía para la refactorización?

0 commit comments

Comments
 (0)