A Java, Principis SOLIDS són un enfocament orientat a objectes que s'apliquen al disseny d'estructura de programari. Està conceptualitzat per Robert C. Martin (també conegut com l'oncle Bob). Aquests cinc principis han canviat el món de la programació orientada a objectes i també han canviat la manera d'escriure programari. També garanteix que el programari sigui modular, fàcil d'entendre, depurar i refactoritzar. En aquesta secció, parlarem Principis SOLID en Java amb l'exemple adequat .
L'acrònim de la paraula SOLID de:
- Principi de responsabilitat única (SRP)
- Principi obert-tancat (OCP)
- Principi de substitució de Liskov (LSP)
- Principi de segregació de la interfície (ISP)
- Principi d'inversió de dependència (DIP)
Expliquem els principis un per un amb detall.
Principi de responsabilitat única
El principi de responsabilitat única ho diu cada classe Java ha de realitzar una única funcionalitat . La implementació de múltiples funcionalitats en una sola classe combina el codi i, si es requereix alguna modificació, pot afectar tota la classe. Precís el codi i el codi es pot mantenir fàcilment. Entenem el principi de responsabilitat única a través d'un exemple.
Suposem, Estudiant és una classe que té tres mètodes, a saber printDetails(), calcularPercentage(), i addStudent(). Per tant, la classe Estudiant té tres responsabilitats per imprimir els detalls dels estudiants, calcular percentatges i base de dades. Mitjançant l'ús del principi de responsabilitat única, podem separar aquestes funcionalitats en tres classes separades per complir l'objectiu del principi.
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 fragment de codi anterior infringeix el principi de responsabilitat única. Per aconseguir l'objectiu del principi, hauríem d'implementar una classe separada que només faci una única funcionalitat.
Student.java
public class Student { public void addStudent(); { //functionality of the method } }
PrintStudentDetails.java
np.sum
public class PrintStudentDetails { public void printDetails(); { //functionality of the method } }
Percentatge.java
public class Percentage { public void calculatePercentage(); { //functionality of the method } }
Per tant, hem assolit l'objectiu del principi de responsabilitat única separant la funcionalitat en tres classes separades.
Principi obert-tancat
L'aplicació o mòdul engloba els mètodes, funcions, variables, etc. El principi obert-tancat estableix que segons els nous requeriments el mòdul hauria d'estar obert per ampliar però tancat per modificar-lo. L'extensió ens permet implementar noves funcionalitats al mòdul. Entenem el principi a través d'un exemple.
Suposem, Informació del vehicle és una classe i té el mètode vehicleNumber() que retorna el número del vehicle.
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 volem afegir una altra subclasse anomenada Truck, simplement, afegim una declaració if més que viola el principi obert-tancat. L'única manera d'afegir la subclasse i assolir l'objectiu de principi anul·lant el vehicleNumber() mètode, com hem mostrat a continuació.
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 la mateixa manera, podem afegir més vehicles fent una altra subclasse que s'estengui de la classe de vehicles. l'enfocament no afectaria l'aplicació existent.
Principi de substitució de Liskov
El principi de substitució de Liskov (LSP) va ser introduït per Bàrbara Liskov . S'aplica a l'herència de manera que el les classes derivades han de ser completament substituïbles per les seves classes base . En altres paraules, si la classe A és un subtipus de la classe B, hauríem de ser capaços de substituir B per A sense interrompre el comportament del programa.
Estén el principi d'obertura-tancament i també se centra en el comportament d'una superclasse i els seus subtipus. Hauríem de dissenyar les classes per preservar la propietat tret que tinguem una raó sòlida per fer el contrari. Entenem el principi a través d'un exemple.
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); } }
Les classes anteriors infringeixen el principi de substitució de Liskov perquè la classe StudentBMI té restriccions addicionals, és a dir, l'alçada i el pes que han de ser els mateixos. Per tant, la classe Student (classe base) no es pot substituir per la classe StudentBMI (classe derivada).
Per tant, substituir la classe Student per la classe StudentBMI pot provocar un comportament inesperat.
Principi de segregació de la interfície
El principi estableix que les interfícies més grans es divideixen en altres més petites. Perquè les classes d'implementació només utilitzen els mètodes necessaris. No hem d'obligar el client a utilitzar els mètodes que no vol utilitzar.
L'objectiu del principi de segregació d'interfícies és similar al principi de responsabilitat única. Entenem el principi a través d'un exemple.
Suposem que hem creat una interfície anomenada Conversió tenint tres mètodes intToDouble(), intToChar(), i charToString() .
public interface Conversion { public void intToDouble(); public void intToChar(); public void charToString(); }
La interfície anterior té tres mètodes. Si volem utilitzar només un mètode intToChar(), no tenim cap opció per implementar el mètode únic. Per superar el problema, el principi ens permet dividir la interfície en tres separades.
public interface ConvertIntToDouble { public void intToDouble(); } public interface ConvertIntToChar { public void intToChar(); } public interface ConvertCharToString { public void charToString(); }
Ara només podem utilitzar el mètode que es requereix. Suposem que volem convertir l'enter en doble i el caràcter en cadena, llavors només utilitzarem els mètodes intToDouble() i charToString().
public class DataTypeConversion implements ConvertIntToDouble, ConvertCharToString { public void intToDouble() { //conversion logic } public void charToString() { //conversion logic } }
Principi d'inversió de dependència
El principi estableix que hem d'utilitzar l'abstracció (classes abstractes i interfícies) en lloc d'implementacions concretes. Els mòduls d'alt nivell no haurien de dependre del mòdul de baix nivell, però tots dos haurien de dependre de l'abstracció. Perquè l'abstracció no depèn del detall sinó que el detall depèn de l'abstracció. Desacobla el programari. Entenem el principi a través d'un exemple.
public class WindowsMachine { //functionality }
Val la pena, si no tenim teclat i ratolí per treballar a Windows. Per resoldre aquest problema, creem un constructor de la classe i afegim les instàncies del teclat i del monitor. Després d'afegir les instàncies, la classe té l'aspecte següent:
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 } }
Ara podem treballar a la màquina Windows amb l'ajuda d'un teclat i un ratolí. Però encara ens enfrontem al problema. Perquè hem unit estretament les tres classes mitjançant la paraula clau nova. És difícil provar la màquina de Windows de classe.
Per fer que el codi s'acobli de manera lliure, desacoblarem la màquina de Windows del teclat mitjançant la interfície del teclat i aquesta paraula clau.
inicialització de primavera
Keyboard.java
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; } }
Al codi anterior, hem utilitzat la injecció de dependència per afegir la dependència del teclat a la classe WindowsMachine. Per tant, hem desacoblat les classes.
Per què hem d'utilitzar els principis SOLID?
- Redueix les dependències de manera que un bloc de codi es pot canviar sense afectar els altres blocs de codi.
- Els principis pretenen fer el disseny més fàcil, comprensible.
- Mitjançant l'ús dels principis, el sistema es pot mantenir, es pot provar, escalable i reutilitzable.
- Evita el mal disseny del programari.
La propera vegada que dissenyeu programari, tingueu en compte aquests cinc principis. En aplicar aquests principis, el codi serà molt més clar, comprovable i prescindible.