U Javi, SOLID principi su objektno orijentirani pristup koji se primjenjuje na dizajn strukture softvera. Koncipiran je po Robert C. Martin (također poznat kao ujak Bob). Ovih pet principa promijenilo je svijet objektno orijentiranog programiranja, a promijenilo je i način pisanja softvera. Također osigurava da je softver modularan, lak za razumijevanje, otklanjanje pogrešaka i refaktor. U ovom odjeljku ćemo raspravljati SOLID principi u Javi uz pravi primjer .
Riječ SOLID je akronim za:
- Načelo jedinstvene odgovornosti (SRP)
- Princip otvoreno-zatvoreno (OCP)
- Liskovljev princip supstitucije (LSP)
- Princip segregacije sučelja (ISP)
- Načelo inverzije ovisnosti (DIP)
Objasnimo principe jedan po jedan u detalje.
Načelo jedinstvene odgovornosti
Načelo jedinstvene odgovornosti kaže da svaka Java klasa mora obavljati jednu funkciju . Implementacija višestrukih funkcija u jednoj klasi kombinira kod i ako je potrebna bilo kakva izmjena može utjecati na cijelu klasu. Precizan je kod i kod se može lako održavati. Shvatimo načelo jedinstvene odgovornosti kroz primjer.
Pretpostavimo, Student je klasa koja ima tri metode naime printDetails(), izračunaj postotak(), i dodajStudent(). Dakle, klasa Student ima tri odgovornosti za ispis pojedinosti o studentima, izračunavanje postotaka i baze podataka. Korištenjem načela jedinstvene odgovornosti, možemo razdvojiti te funkcionalnosti u tri odvojene klase kako bismo ispunili cilj načela.
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 } }
Gornji isječak koda krši načelo jedinstvene odgovornosti. Da bismo postigli cilj načela, trebali bismo implementirati zasebnu klasu koja izvodi samo jednu funkcionalnost.
Student.java
java izbaci iznimku
public class Student { public void addStudent(); { //functionality of the method } }
PrintStudentDetails.java
public class PrintStudentDetails { public void printDetails(); { //functionality of the method } }
Postotak.java
public class Percentage { public void calculatePercentage(); { //functionality of the method } }
Dakle, postigli smo cilj načela jedinstvene odgovornosti razdvajanjem funkcionalnosti u tri odvojene klase.
Princip otvoreno-zatvoreno
Aplikacija ili modul sadrži metode, funkcije, varijable itd. Načelo otvoreno-zatvoreno navodi da prema novim zahtjevima modul bi trebao biti otvoren za proširenje, ali zatvoren za modifikaciju. Proširenje nam omogućuje implementaciju nove funkcionalnosti u modul. Shvatimo princip kroz primjer.
Pretpostavimo, Podaci o vozilu je klasa i ima metodu Broj vozila() koji vraća broj vozila.
Podaci o vozilu.java
public class VehicleInfo { public double vehicleNumber(Vehicle vcl) { if (vcl instanceof Car) { return vcl.getNumber(); if (vcl instanceof Bike) { return vcl.getNumber(); } }
Ako želimo dodati još jednu podklasu pod nazivom Kamion, jednostavno, dodamo još jednu if naredbu koja krši načelo otvoreno-zatvoreno. Jedini način za dodavanje podklase i postizanje načelnog cilja nadjačavanjem Broj vozila() metoda, kao što smo pokazali u nastavku.
Podaci o vozilu.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(); }
Slično tome, možemo dodati više vozila stvaranjem druge podklase koja se proširuje iz klase vozila. pristup ne bi utjecao na postojeću aplikaciju.
Načelo Liskovljeve supstitucije
Liskovljev princip supstitucije (LSP) uveo je Barbara Liskov . Primjenjuje se na nasljeđivanje na takav način da izvedene klase moraju biti potpuno zamjenjive za svoje osnovne klase . Drugim riječima, ako je klasa A podtip klase B, tada bismo trebali biti u mogućnosti zamijeniti B s A bez prekidanja ponašanja programa.
Proširuje načelo otvaranja i zatvaranja i također se fokusira na ponašanje superklase i njenih podtipova. Trebali bismo osmisliti klase kako bismo očuvali imovinu osim ako nemamo jak razlog da učinimo drugačije. Shvatimo princip kroz primjer.
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); } }
Gornje klase prekršile su Liskovovo načelo zamjene jer klasa Student BMI ima dodatna ograničenja, tj. visinu i težinu koje moraju biti iste. Stoga se klasa Student (osnovna klasa) ne može zamijeniti klasom Student BMI (izvedena klasa).
Stoga zamjena klase Student s klasom Student BMI može rezultirati neočekivanim ponašanjem.
Načelo razdvajanja sučelja
Načelo kaže da se veća sučelja dijele na manja. Zato što implementacijske klase koriste samo metode koje su potrebne. Ne bismo trebali prisiljavati klijenta da koristi metode koje ne želi koristiti.
Cilj načela razdvajanja sučelja sličan je načelu jedinstvene odgovornosti. Shvatimo princip kroz primjer.
Pretpostavimo da smo kreirali sučelje pod nazivom Pretvorba ima tri metode intToDouble(), intToChar(), i charToString() .
public interface Conversion { public void intToDouble(); public void intToChar(); public void charToString(); }
Gornje sučelje ima tri metode. Ako želimo koristiti samo metodu intToChar(), nemamo izbora implementirati jednu metodu. Kako bismo prevladali problem, princip nam omogućuje da podijelimo sučelje u tri odvojena.
public interface ConvertIntToDouble { public void intToDouble(); } public interface ConvertIntToChar { public void intToChar(); } public interface ConvertCharToString { public void charToString(); }
Sada možemo koristiti samo onu metodu koja je potrebna. Pretpostavimo da želimo pretvoriti cijeli broj u dvostruki i znak u niz, a zatim ćemo koristiti samo metode intToDouble() i charToString().
public class DataTypeConversion implements ConvertIntToDouble, ConvertCharToString { public void intToDouble() { //conversion logic } public void charToString() { //conversion logic } }
Načelo inverzije ovisnosti
Načelo kaže da moramo koristiti apstrakciju (apstraktne klase i sučelja) umjesto konkretnih implementacija. Moduli visoke razine ne bi trebali ovisiti o modulu niske razine, ali bi oba trebala ovisiti o apstrakciji. Jer apstrakcija ne ovisi o detaljima, već detalj ovisi o apstrakciji. Odvaja softver. Shvatimo princip kroz primjer.
public class WindowsMachine { //functionality }
Isplati se, ako nemamo tipkovnicu i miš raditi na Windowsima. Da bismo riješili ovaj problem, kreiramo konstruktor klase i dodamo instance tipkovnice i monitora. Nakon dodavanja instanci, klasa izgleda ovako:
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 } }
Sada možemo raditi na Windows stroju uz pomoć tipkovnice i miša. Ali i dalje se suočavamo s problemom. Budući da smo usko spojili tri klase pomoću nove ključne riječi. Teško je testirati Class Windows stroj.
koliko je gradova u nas
Kako bi kod bio labavo povezan, odvajamo WindowsMachine od tipkovnice pomoću sučelja tipkovnice i ove ključne riječi.
Tipkovnica.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; } }
U gornjem kodu upotrijebili smo ubrizgavanje ovisnosti za dodavanje ovisnosti tipkovnice u klasi WindowsMachine. Stoga smo razdvojili razrede.
Zašto bismo trebali koristiti načela SOLID-a?
- Smanjuje ovisnosti tako da se blok koda može promijeniti bez utjecaja na ostale blokove koda.
- Načela namijenjena da dizajn učine lakšim, razumljivijim.
- Korištenjem načela, sustav je moguće održavati, testirati, skalabilan i ponovno koristiti.
- Izbjegava loš dizajn softvera.
Kad sljedeći put budete dizajnirali softver, imajte na umu ovih pet načela. Primjenom ovih načela, kod će biti mnogo jasniji, testiraniji i višestruki.