Definicja
Zasada pojedynczej odpowiedzialności (ang. Single Responsibility Principle, SRP) mówi, że każda klasa, moduł lub funkcja powinna mieć tylko jeden powód do zmiany. Innymi słowy – każda część kodu powinna zajmować się tylko jednym, jasno określonym zadaniem. Dzięki temu kod staje się prostszy, bardziej przejrzysty i łatwiejszy w utrzymaniu.


Przykład z życia
Wyobraźmy sobie fabrykę prefabrykatów żelbetowych, która produkuje belki i płyty.
Pracownik linii produkcyjnej ma dwa zadania:
- kontrolować jakość elementów,
- oraz przygotowywać raporty do działu sprzedaży.
W praktyce to nieefektywne — jeśli pracownik zajmuje się wszystkim, może popełnić błędy lub spowolnić proces. Lepiej, aby jedna osoba odpowiadała za kontrolę jakości, a inna za raportowanie.
To samo dotyczy kodu — klasa powinna mieć jedną odpowiedzialność, a nie próbować „robić wszystkiego naraz”.
Przykłady przed i po zastosowaniu zasady
PRZED
Przykład poniżej przedstawia klasę, która narusza zasadę SRP — zajmuje się zarówno obliczaniem masy prefabrykatu, jak i generowaniem raportu.
Klasa PrefabElement odpowiada zarówno za logikę obliczeniową, jak i za generowanie raportu.
Jeśli zmieni się sposób raportowania (np. raport ma być zapisywany do pliku CSV zamiast drukowany), trzeba będzie zmienić klasę, mimo że nie dotyczy to jej głównej funkcji (obliczeń).
public class PrefabElement {
private double length;
private double width;
private double height;
private double density;
public PrefabElement(double length, double width, double height, double density) {
this.length = length;
this.width = width;
this.height = height;
this.density = density;
}
public double calculateWeight() {
return length * width * height * density;
}
public void generateReport() {
double weight = calculateWeight();
String report = "Prefab element: " + length + "x" + width + "x" + height + " m\n"
+ "Weight: " + weight + " kg\n"
+ "Report generated for production control.";
System.out.println(report);
}
public static void main(String[] args) {
PrefabElement beam = new PrefabElement(6.0, 0.3, 0.5, 2500.0);
beam.generateReport();
}
}

PO
Po wprowadzeniu zasady SRP rozdzielamy obowiązki na dwie klasy:
-PrefabElement – odpowiada tylko za dane i obliczenia,
-ReportGenerator – odpowiada za tworzenie raportów.
Teraz każda klasa ma jedną, jasno określoną odpowiedzialność:
-PrefabElement → obliczenia techniczne,
-ReportGenerator → prezentacja i raportowanie.
Jeśli w przyszłości zmienimy sposób generowania raportów (np. eksport do PDF), wystarczy zmodyfikować tylko ReportGenerator, a nie dotykać logiki obliczeń.
// Klasa odpowiedzialna tylko za dane i obliczenia techniczne
public class PrefabElement {
private double length;
private double width;
private double height;
private double density;
public PrefabElement(double length, double width, double height, double density) {
this.length = length;
this.width = width;
this.height = height;
this.density = density;
}
public double calculateWeight() {
return length * width * height * density;
}
public double getLength() {
return length;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
}
// Klasa odpowiedzialna tylko za generowanie raportu
public class ReportGenerator {
public void generate(PrefabElement element) {
double weight = element.calculateWeight();
String report = "Prefab element: " + element.getLength() + "x"
+ element.getWidth() + "x" + element.getHeight() + " m\n"
+ "Weight: " + weight + " kg\n"
+ "Report generated for production control.";
System.out.println(report);
}
}
// Klasa główna – przykład użycia
public class Main {
public static void main(String[] args) {
PrefabElement beam = new PrefabElement(6.0, 0.3, 0.5, 2500.0);
ReportGenerator reporter = new ReportGenerator();
reporter.generate(beam);
}
}
Kiedy zasada jest ważna?
- projekt rośnie i wiele osób pracuje nad kodem,
- wprowadzane są częste zmiany w różnych aspektach systemu (np. obliczenia, raportowanie, logowanie).
- Nie zawsze jednak warto rozbijać wszystko na drobne klasy — czasem proste skrypty lub prototypy mogą być bardziej praktyczne w formie jednej klasy.
Na co zwracać uwagę:
- Czy klasa ma więcej niż jeden powód, by się zmienić?
- Czy zmiana w jednym obszarze (np. raportowanie) nie wpływa na inny (np. obliczenia)?
Trudności:
- Początkujący często próbują „nadmiernie rozdzielać” klasy, co prowadzi do zbyt dużej liczby plików i komplikacji.
- Ważna jest równowaga między czystością kodu a jego praktycznością.
