|
| 1 | +//EJERCICIO |
1 | 2 | /*
|
2 |
| - * EJERCICIO: |
3 |
| - * Explora el "Principio SOLID Abierto-Cerrado (Open-Close Principle, OCP)" |
4 |
| - * y crea un ejemplo simple donde se muestre su funcionamiento |
5 |
| - * de forma correcta e incorrecta. |
6 |
| - * |
7 |
| - * DIFICULTAD EXTRA (opcional): |
8 |
| - * Desarrolla una calculadora que necesita realizar diversas operaciones matemáticas. |
9 |
| - * Requisitos: |
10 |
| - * - Debes diseñar un sistema que permita agregar nuevas operaciones utilizando el OCP. |
11 |
| - * Instrucciones: |
12 |
| - * 1. Implementa las operaciones de suma, resta, multiplicación y división. |
13 |
| - * 2. Comprueba que el sistema funciona. |
14 |
| - * 3. Agrega una quinta operación para calcular potencias. |
15 |
| - * 4. Comprueba que se cumple el OCP. |
16 |
| - */ |
| 3 | +Incorrecto ❎ |
| 4 | +
|
| 5 | +Dado a que no se ha diseñado siguiendo el principio, habría que modificar clases para que el sistema de cálculo de áreas pueda soportar otras figuras geométricas. En un caso más complejo este sería un problema, ya que dificulta el agregar funcionalidades o realizar cambios. |
| 6 | +
|
| 7 | +*/ |
| 8 | +console.log('\nSin OCP'); |
| 9 | +class RectangleNoOCP { |
| 10 | + constructor(height, width) { |
| 11 | + this.height = height; |
| 12 | + this.width = width; |
| 13 | + } |
| 14 | +} |
| 15 | +class AreaCalculatorNoOCP { |
| 16 | + calculateArea(rectangle) { |
| 17 | + let area = rectangle.height * rectangle.width; |
| 18 | + |
| 19 | + return area; |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +class AppNoOCP { |
| 24 | + rectangle = new RectangleNoOCP(12, 20.33); |
| 25 | + square = new RectangleNoOCP(21, 21); |
| 26 | + |
| 27 | + areaCalc = new AreaCalculatorNoOCP(); |
| 28 | + |
| 29 | + displayAreas() { |
| 30 | + console.log('Rectangulo:', this.areaCalc.calculateArea(this.rectangle)); |
| 31 | + console.log('Cuadrado:', this.areaCalc.calculateArea(this.square)); |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +const appNoOCP = new AppNoOCP(); |
| 36 | +appNoOCP.displayAreas(); |
17 | 37 |
|
18 |
| -//EJERCICIO |
19 | 38 | /*
|
20 |
| -PRINCIPIO ABIERTO-CERRADO: |
| 39 | +Correcto ✅ |
| 40 | +
|
| 41 | +"Las entidades de software (clases, módulos, funciones, etc) deben de estar abierta para su extensión, pero cerradas para su modificación." |
21 | 42 |
|
22 |
| -"Las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas para su extensión, pero cerradas para su modificación" |
| 43 | +Diseñado de esta manera resulta más fácil añadir figuras geométricas al sistema de cálculo de áreas. Este ejemplo abstrae el método getArea y lo hace común para cada figura, pero cada una cuenta con su propio método concreto para calcular el área. |
23 | 44 |
|
24 | 45 | */
|
| 46 | +console.log('\nCon OCP'); |
| 47 | + |
| 48 | +class GeometricShape { |
| 49 | + constructor() { |
| 50 | + this.area = this.getArea(); |
| 51 | + } |
| 52 | + |
| 53 | + getArea() { |
| 54 | + return false; |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +class Rectangle extends GeometricShape { |
| 59 | + constructor(height, width) { |
| 60 | + super(); |
| 61 | + this.height = height; |
| 62 | + this.width = width; |
| 63 | + } |
| 64 | + |
| 65 | + getArea() { |
| 66 | + return this.height * this.width; |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +class Square extends GeometricShape { |
| 71 | + constructor(height) { |
| 72 | + super(); |
| 73 | + this.height = height; |
| 74 | + } |
| 75 | + |
| 76 | + getArea() { |
| 77 | + return this.height ** 2; |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +class Circle extends GeometricShape { |
| 82 | + constructor(radius) { |
| 83 | + super(); |
| 84 | + this.radius = radius; |
| 85 | + } |
| 86 | + |
| 87 | + getArea() { |
| 88 | + return this.radius * 2 * Math.PI; |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +class AreaCalculator { |
| 93 | + calculateArea(shape) { |
| 94 | + return shape.getArea(); //puede usarse shape.area también |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +class App { |
| 99 | + rectangle = new Rectangle(12, 20); |
| 100 | + square = new Square(20); |
| 101 | + circle = new Circle(5); |
| 102 | + |
| 103 | + areaCalc = new AreaCalculator(); |
| 104 | + |
| 105 | + displayAreas() { |
| 106 | + console.log('Rectangulo:', this.areaCalc.calculateArea(this.rectangle)); |
| 107 | + console.log('Cuadrado:', this.areaCalc.calculateArea(this.square)); |
| 108 | + console.log('Circulo:', this.areaCalc.calculateArea(this.circle)); |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | +const app = new App(); |
| 113 | + |
| 114 | +app.displayAreas(); |
25 | 115 |
|
26 | 116 | //EXTRA
|
27 |
| -class Calculator { |
28 |
| - display(operation, a, b) { |
29 |
| - const operationOptions = { |
30 |
| - add: this.add, |
31 |
| - susbtrac: this.susbtrac, |
32 |
| - multiplicate: this.multiplicate, |
33 |
| - divide: this.divide, |
34 |
| - }; |
| 117 | +console.log('\nCalculadora'); |
| 118 | +class Operation { |
| 119 | + constructor(name) { |
| 120 | + this.name = name; |
| 121 | + } |
35 | 122 |
|
36 |
| - function defaultfun() { |
37 |
| - console.log('Operacion no soportada o inexistente'); |
38 |
| - } |
| 123 | + calculate(a, b) { |
| 124 | + return 'Operación no soportada'; |
| 125 | + } |
| 126 | +} |
39 | 127 |
|
40 |
| - const fun = operationOptions[operation] || defaultfun; |
| 128 | +class Add extends Operation { |
| 129 | + calculate(a, b) { |
| 130 | + return a + b; |
| 131 | + } |
| 132 | +} |
41 | 133 |
|
42 |
| - fun(a, b); |
| 134 | +class Susbtrac extends Operation { |
| 135 | + calculate(a, b) { |
| 136 | + return a - b; |
43 | 137 | }
|
| 138 | +} |
44 | 139 |
|
45 |
| - add(a, b) { |
46 |
| - console.log(a + b); |
| 140 | +class Multiply extends Operation { |
| 141 | + calculate(a, b) { |
| 142 | + return a * b; |
47 | 143 | }
|
| 144 | +} |
48 | 145 |
|
49 |
| - susbtrac(a, b) { |
50 |
| - console.log(a - b); |
| 146 | +class Divide extends Operation { |
| 147 | + calculate(a, b) { |
| 148 | + return a / b; |
51 | 149 | }
|
| 150 | +} |
| 151 | + |
| 152 | +class Calculator { |
| 153 | + #operations = []; |
52 | 154 |
|
53 |
| - multiplicate(a, b) { |
54 |
| - console.log(a * b); |
| 155 | + addOperation(operation) { |
| 156 | + this.#operations.push(operation); |
55 | 157 | }
|
56 | 158 |
|
57 |
| - divide(a, b) { |
58 |
| - console.log(a / b); |
| 159 | + calculate(operation, a, b) { |
| 160 | + let fun = new Operation().calculate; |
| 161 | + |
| 162 | + this.#operations.forEach((op) => { |
| 163 | + if (op.name === operation) { |
| 164 | + fun = op.calculate; |
| 165 | + } |
| 166 | + }); |
| 167 | + |
| 168 | + return fun(a, b); |
59 | 169 | }
|
60 | 170 | }
|
61 | 171 |
|
62 | 172 | const calculator = new Calculator();
|
63 | 173 |
|
64 |
| -calculator.display('add', 12, 10); |
65 |
| -calculator.display('potencia', 12, 10); |
| 174 | +calculator.addOperation(new Add('Suma')); |
| 175 | +calculator.addOperation(new Susbtrac('Resta')); |
| 176 | +calculator.addOperation(new Multiply('Multiplicación')); |
| 177 | +calculator.addOperation(new Divide('División')); |
| 178 | + |
| 179 | +console.log('Suma:', calculator.calculate('Suma', 10, 1)); |
| 180 | +console.log('Resta:', calculator.calculate('Resta', 10, 1)); |
| 181 | +console.log('Multiplicación:', calculator.calculate('Multiplicación', 4, 2)); |
| 182 | +console.log('División:', calculator.calculate('División', 10, 2)); |
| 183 | +console.log('Potencia:', calculator.calculate('Potencia', 3, 2)); |
| 184 | + |
| 185 | +class Exponent extends Operation { |
| 186 | + calculate(a, b) { |
| 187 | + return a ** b; |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +calculator.addOperation(new Exponent('Potencia')); |
| 192 | +console.log('Potencia:', calculator.calculate('Potencia', 3, 2)); |
0 commit comments