En Java, Principios SÓLIDOS son un enfoque orientado a objetos que se aplican al diseño de estructuras de software. Está conceptualizado por Roberto C. Martín (también conocido como tío Bob). Estos cinco principios han cambiado el mundo de la programación orientada a objetos y también la forma de escribir software. También garantiza que el software sea modular, fácil de entender, depurar y refactorizar. En esta sección, discutiremos Principios SÓLIDOS en Java con el ejemplo adecuado .
La palabra SÓLIDO acrónimo de:
- Principio de Responsabilidad Única (SRP)
- Principio abierto-cerrado (OCP)
- Principio de sustitución de Liskov (LSP)
- Principio de segregación de interfaz (ISP)
- Principio de inversión de dependencia (DIP)
Expliquemos los principios uno por uno en detalle.
Principio de responsabilidad única
El principio de responsabilidad única establece que cada clase de Java debe realizar una única funcionalidad . La implementación de múltiples funcionalidades en una sola clase mashup el código y si se requiere alguna modificación puede afectar a toda la clase. Es preciso el código y el código se puede mantener fácilmente. Entendamos el principio de responsabilidad única a través de un ejemplo.
Suponer, Alumno es una clase que tiene tres métodos, a saber imprimirDetalles(), calcularPorcentaje(), y agregarEstudiante(). Por lo tanto, la clase Estudiante tiene tres responsabilidades: imprimir los detalles de los estudiantes, calcular porcentajes y la base de datos. Al utilizar el principio de responsabilidad única, podemos separar estas funcionalidades en tres clases separadas para cumplir el objetivo del principio.
Student.java
public class Student { public void printDetails(); { //functionality of the method } pubic void calculatePercentage(); { //functionality of the method } public void addStudent(); { //functionality of the method } }
El fragmento de código anterior viola el principio de responsabilidad única. Para lograr el objetivo del principio, debemos implementar una clase separada que realice una única funcionalidad.
Student.java
public class Student { public void addStudent(); { //functionality of the method } }
PrintStudentDetails.java
public class PrintStudentDetails { public void printDetails(); { //functionality of the method } }
Percentage.java
si por rudyard kipling explicación línea por línea
public class Percentage { public void calculatePercentage(); { //functionality of the method } }
Por lo tanto, hemos logrado el objetivo del principio de responsabilidad única al separar la funcionalidad en tres clases separadas.
Principio abierto-cerrado
La aplicación o módulo entidades los métodos, funciones, variables, etc. El principio abierto-cerrado establece que de acuerdo con nuevos requisitos el módulo debe estar abierto para ampliación pero cerrado para modificación. La extensión nos permite implementar nuevas funciones en el módulo. Entendamos el principio a través de un ejemplo.
Suponer, Información del vehículo es una clase y tiene el método número de vehículo() que devuelve el número del vehículo.
VehicleInfo.java
public class VehicleInfo { public double vehicleNumber(Vehicle vcl) { if (vcl instanceof Car) { return vcl.getNumber(); if (vcl instanceof Bike) { return vcl.getNumber(); } }
Si queremos agregar otra subclase llamada Truck, simplemente agregamos una declaración if más que viola el principio de apertura y cierre. La única forma de agregar la subclase y lograr el objetivo del principio anulando la número de vehículo() método, como hemos mostrado a continuación.
VehicleInfo.java
public class VehicleInfo { public double vehicleNumber() { //functionality } } public class Car extends VehicleInfo { public double vehicleNumber() { return this.getValue(); } public class Car extends Truck { public double vehicleNumber() { return this.getValue(); }
De manera similar, podemos agregar más vehículos creando otra subclase que se extienda desde la clase de vehículo. el enfoque no afectaría la aplicación existente.
Principio de sustitución de Liskov
El principio de sustitución de Liskov (LSP) fue introducido por Barbara Liškov . Se aplica a la herencia de tal manera que el las clases derivadas deben ser completamente sustituibles por sus clases base . En otras palabras, si la clase A es un subtipo de la clase B, entonces deberíamos poder reemplazar B con A sin interrumpir el comportamiento del programa.
Amplía el principio de apertura y cierre y también se centra en el comportamiento de una superclase y sus subtipos. Deberíamos diseñar las clases para preservar la propiedad a menos que tengamos una buena razón para hacerlo de otra manera. Entendamos el principio a través de un ejemplo.
Student.java
public class Student { private double height; private double weight; public void setHeight(double h) { height = h; } public void setWeight(double w) { weight= w; } ... } public class StudentBMI extends Student { public void setHeight(double h) { super.setHeight(h); super.setWeight(w); } public void setWeight(double h) { super.setHeight(h); super.setWeight(w); } }
Las clases anteriores violaron el principio de sustitución de Liskov porque la clase StudentBMI tiene restricciones adicionales, es decir, altura y peso que deben ser iguales. Por lo tanto, la clase Student (clase base) no puede ser reemplazada por la clase StudentBMI (clase derivada).
Por lo tanto, sustituir la clase Student por la clase StudentBMI puede dar como resultado un comportamiento inesperado.
Principio de segregación de interfaz
El principio establece que las interfaces más grandes se dividen en otras más pequeñas. Porque las clases de implementación utilizan sólo los métodos necesarios. No debemos obligar al cliente a utilizar métodos que no quiere utilizar.
El objetivo del principio de segregación de interfaces es similar al principio de responsabilidad única. Entendamos el principio a través de un ejemplo.
Supongamos que hemos creado una interfaz llamada Conversión teniendo tres métodos intToDouble(), intToChar(), y charToString() .
public interface Conversion { public void intToDouble(); public void intToChar(); public void charToString(); }
La interfaz anterior tiene tres métodos. Si queremos utilizar sólo un método intToChar(), no tenemos opción de implementar el método único. Para superar el problema, el principio nos permite dividir la interfaz en tres partes separadas.
public interface ConvertIntToDouble { public void intToDouble(); } public interface ConvertIntToChar { public void intToChar(); } public interface ConvertCharToString { public void charToString(); }
Ahora podemos utilizar sólo el método que se requiere. Supongamos que queremos convertir el número entero en doble y el carácter en cadena, entonces usaremos solo los métodos intToDouble() y charToString().
public class DataTypeConversion implements ConvertIntToDouble, ConvertCharToString { public void intToDouble() { //conversion logic } public void charToString() { //conversion logic } }
Principio de inversión de dependencia
El principio establece que debemos utilizar abstracciones (clases e interfaces abstractas) en lugar de implementaciones concretas. Los módulos de alto nivel no deberían depender del módulo de bajo nivel, pero ambos deberían depender de la abstracción. Porque la abstracción no depende del detalle sino que el detalle depende de la abstracción. Desacopla el software. Entendamos el principio a través de un ejemplo.
public class WindowsMachine { //functionality }
Merece la pena, si no disponemos de teclado y ratón, para trabajar en Windows. Para solucionar este problema, creamos un constructor de la clase y agregamos las instancias del teclado y el monitor. Después de agregar las instancias, la clase tiene el siguiente aspecto:
public class WindowsMachine { public final keyboard; public final monitor; public WindowsMachine() { monitor = new monitor(); //instance of monitor class keyboard = new keyboard(); //instance of keyboard class } }
Ahora podemos trabajar en la máquina Windows con la ayuda de un teclado y un mouse. Pero todavía nos enfrentamos al problema. Porque hemos acoplado estrechamente las tres clases usando la nueva palabra clave. Es difícil probar la máquina con Windows de clase.
Para que el código esté ligeramente acoplado, desacoplamos WindowsMachine del teclado mediante la interfaz del teclado y esta palabra clave.
Keyboard.java
sistema.out.println
public interface Keyboard { //functionality }
WindowsMachine.java
public class WindowsMachine { private final Keyboard keyboard; private final Monitor monitor; public WindowsMachine(Keyboard keyboard, Monitor monitor) { this.keyboard = keyboard; this.monitor = monitor; } }
En el código anterior, hemos utilizado la inyección de dependencia para agregar la dependencia del teclado en la clase WindowsMachine. Por lo tanto, hemos desacoplado las clases.
¿Por qué deberíamos utilizar principios SÓLIDOS?
- Reduce las dependencias para que se pueda cambiar un bloque de código sin afectar a los demás bloques de código.
- Los principios destinados a hacer el diseño más fácil y comprensible.
- Al utilizar los principios, el sistema es mantenible, comprobable, escalable y reutilizable.
- Evita el mal diseño del software.
La próxima vez que diseñe software, tenga en cuenta estos cinco principios. Al aplicar estos principios, el código será mucho más claro, comprobable y prescindible.