Skip to content

Commit 53c129f

Browse files
mouredev#28 - typescript
1 parent 28971df commit 53c129f

File tree

2 files changed

+209
-2
lines changed

2 files changed

+209
-2
lines changed

Roadmap/27 - SOLID OCP/typescript/duendeintemporal.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
//#27 - { retosparaprogramadores } Principio SOLID Abierto-Cerrado (Open-Close Principle, OCP)
22

3+
/*
4+
* EJERCICIO:
5+
* Explora el "Principio SOLID Abierto-Cerrado (Open-Close Principle, OCP)"
6+
* y crea un ejemplo simple donde se muestre su funcionamiento
7+
* de forma correcta e incorrecta.
8+
*
9+
* DIFICULTAD EXTRA (opcional):
10+
* Desarrolla una calculadora que necesita realizar diversas operaciones matemáticas.
11+
* Requisitos:
12+
* - Debes diseñar un sistema que permita agregar nuevas operaciones utilizando el OCP.
13+
* Instrucciones:
14+
* 1. Implementa las operaciones de suma, resta, multiplicación y división.
15+
* 2. Comprueba que el sistema funciona.
16+
* 3. Agrega una quinta operación para calcular potencias.
17+
* 4. Comprueba que se cumple el OCP.
18+
*/
19+
320
// https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle
4-
/* In object-oriented programming, the open–closed principle (OCP) states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.
21+
/* In object-oriented programming, the open–closed principle (OCP) states "software entities (classes,
22+
modules, functions, etc.) should be open for extension, but closed for modification"; that is, such
23+
an entity can allow its behaviour to be extended without modifying its source code.
524
6-
The name open–closed principle has been used in two ways. Both ways use generalizations (for instance, inheritance or delegate functions) to resolve the apparent dilemma, but the goals, techniques, and results are different. */
25+
The name open–closed principle has been used in two ways. Both ways use generalizations (for instance,
26+
inheritance or delegate functions) to resolve the apparent dilemma, but the goals, techniques, and
27+
results are different. */
728

829
let log = console.log;
930

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
//#28 - Principio SOLID de Sustitución de Liskov (Liskov Substitution Principle, LSP)
2+
/*
3+
* EJERCICIO:
4+
* Explora el "Principio SOLID de Sustitución de Liskov (Liskov Substitution Principle, LSP)"
5+
* y crea un ejemplo simple donde se muestre su funcionamiento
6+
* de forma correcta e incorrecta.
7+
*
8+
* DIFICULTAD EXTRA (opcional):
9+
* Crea una jerarquía de vehículos. Todos ellos deben poder acelerar y frenar, así como
10+
* cumplir el LSP.
11+
* Instrucciones:
12+
* 1. Crea la clase Vehículo.
13+
* 2. Añade tres subclases de Vehículo.
14+
* 3. Implementa las operaciones "acelerar" y "frenar" como corresponda.
15+
* 4. Desarrolla un código que compruebe que se cumple el LSP.
16+
*/
17+
18+
/* The Liskov Substitution Principle (LSP) is one of the five SOLID principles of object-oriented programming. This principle states that objects of a derived class should be able to replace objects of the base class without altering the correctness of the program. */
19+
20+
let log = console.log;
21+
22+
// Check if running in a browser environment
23+
const isBrowser = typeof window !== 'undefined';
24+
25+
// Conditional check for browser environment
26+
if (isBrowser) {
27+
window.addEventListener('load', () => {
28+
const body: HTMLBodyElement | null = document.querySelector('body');
29+
const title = document.createElement('h1');
30+
31+
body?.style.setProperty('background', '#000');
32+
body?.style.setProperty('text-align', 'center');
33+
34+
title.textContent = 'Retosparaprogramadores #28.';
35+
title.style.setProperty('font-size', '3.5vmax');
36+
title.style.setProperty('color', '#fff');
37+
title.style.setProperty('line-height', '100vh');
38+
39+
body?.appendChild(title);
40+
41+
setTimeout(() => {
42+
alert('Retosparaprogramadores #28. Please open the Browser Developer Tools.');
43+
}, 2000);
44+
log('Retosparaprogramadores #28');
45+
});
46+
} else {
47+
log('This code is designed to run in a browser environment. Skipping window-related code.');
48+
log('Retosparaprogramadores #28');
49+
}
50+
51+
52+
// Liskov Substitution Principle (LSP) Example
53+
54+
class Shape {
55+
area(): number {
56+
return 0; // Default implementation
57+
}
58+
}
59+
60+
class Rectangle extends Shape {
61+
constructor(private width: number, private height: number) {
62+
super();
63+
}
64+
65+
area(): number {
66+
return this.width * this.height;
67+
}
68+
}
69+
70+
class Square extends Shape {
71+
constructor(private side: number) {
72+
super();
73+
}
74+
75+
area(): number {
76+
return this.side * this.side;
77+
}
78+
}
79+
80+
const calculateArea = (shape: Shape): number => {
81+
return shape.area();
82+
};
83+
84+
const rectangle = new Rectangle(83, 105);
85+
const square = new Square(40);
86+
87+
log(calculateArea(rectangle)); // 8715
88+
log(calculateArea(square)); // 1600
89+
90+
// Extra Difficulty Exercise
91+
92+
// Define the ICar interface
93+
interface ICar {
94+
brand: string;
95+
model: string;
96+
maxSpeed: number;
97+
acceleration: number;
98+
deceleration: number;
99+
}
100+
101+
// Define the Car class
102+
class Car {
103+
constructor(
104+
public brand: string,
105+
public model: string,
106+
public maxSpeed: number,
107+
public acceleration: number,
108+
public deceleration: number,
109+
public currentSpeed: number = 0
110+
) {}
111+
112+
accelerate(seconds: number): void {
113+
const newSpeed = this.currentSpeed + this.acceleration * seconds;
114+
this.currentSpeed = Math.min(newSpeed, this.maxSpeed);
115+
log(`${this.brand} ${this.model} accelerated to ${this.currentSpeed} km/h.`);
116+
}
117+
118+
brake(seconds: number): void {
119+
const newSpeed = this.currentSpeed - this.deceleration * seconds;
120+
this.currentSpeed = Math.max(newSpeed, 0);
121+
log(`${this.brand} ${this.model} braked to ${this.currentSpeed} km/h.`);
122+
}
123+
}
124+
125+
// Define the SportsCar class
126+
class SportsCar extends Car {
127+
constructor(brand: string, model: string, maxSpeed: number, acceleration: number, deceleration: number) {
128+
super(brand, model, maxSpeed, acceleration, deceleration);
129+
}
130+
}
131+
132+
// Define the FamilyCar class
133+
class FamilyCar extends Car {
134+
constructor(brand: string, model: string, maxSpeed: number, acceleration: number, deceleration: number) {
135+
super(brand, model, maxSpeed, acceleration, deceleration);
136+
}
137+
}
138+
139+
/* Note: Originally, the code used the spread operator (...) with Object.values to pass properties to
140+
the constructor, like this:
141+
142+
const sportsCar = new SportsCar(...Object.values(sportsCars[0])
143+
as [string, string, number, number, number]);
144+
145+
While this approach works in some cases, it has a critical flaw: Object.values does not guarantee the
146+
order of properties. This can lead to runtime errors if the order of properties in the object does
147+
not match the order of parameters in the constructor.*/
148+
// That's why switched to using a factory function:
149+
150+
// Factory function for SportsCar
151+
function createSportsCar(carProps: ICar): SportsCar {
152+
const { brand, model, maxSpeed, acceleration, deceleration } = carProps;
153+
return new SportsCar(brand, model, maxSpeed, acceleration, deceleration);
154+
}
155+
156+
// Factory function for FamilyCar
157+
function createFamilyCar(carProps: ICar): FamilyCar {
158+
const { brand, model, maxSpeed, acceleration, deceleration } = carProps;
159+
return new FamilyCar(brand, model, maxSpeed, acceleration, deceleration);
160+
}
161+
162+
// Example data
163+
const sportsCars: ICar[] = [
164+
{ brand: "Ferrari", model: "488", maxSpeed: 330, acceleration: 30, deceleration: 20 },
165+
{ brand: "Porsche", model: "911 Turbo S", maxSpeed: 320, acceleration: 28, deceleration: 18 },
166+
{ brand: "Lamborghini", model: "Huracán", maxSpeed: 325, acceleration: 32, deceleration: 22 }
167+
];
168+
169+
const familyCars: ICar[] = [
170+
{ brand: "Toyota", model: "Sienna", maxSpeed: 180, acceleration: 10, deceleration: 8 },
171+
{ brand: "Honda", model: "Odyssey", maxSpeed: 175, acceleration: 9, deceleration: 7 },
172+
{ brand: "Chrysler", model: "Pacifica", maxSpeed: 180, acceleration: 9, deceleration: 7 }
173+
];
174+
175+
// Create instances using the factory function
176+
const sportsCar = createSportsCar(sportsCars[0]);
177+
const familyCar = createFamilyCar(familyCars[1]);
178+
179+
// Test the cars
180+
function testCar(car: Car, accelerateSeconds: number, brakeSeconds: number): void {
181+
car.accelerate(accelerateSeconds);
182+
car.brake(brakeSeconds);
183+
}
184+
185+
testCar(sportsCar, 5, 2); // Ferrari 488 accelerated to 150 km/h. Ferrari 488 braked to 110 km/h.
186+
testCar(familyCar, 5, 2); // Honda Odyssey accelerated to 45 km/h. Honda Odyssey braked to 31 km/h.

0 commit comments

Comments
 (0)