9 сентября 2025 г.
SRP - Single Responsibility Principle (Принцип единственной ответственности)
Класс должен иметь только одну причину для изменения.
Плохой пример:
public class Employee {
private String name;
private String position;
private double salary;
// Конструкторы, геттеры, сеттеры...
public void saveToDatabase() {
// Сохранение в базу данных
}
public void calculateTax() {
// Расчет налогов
}
public void generateReport() {
// Генерация отчета
}
}
Хороший пример:
public class Employee {
private String name;
private String position;
private double salary;
// Конструкторы, геттеры, сеттеры
}
public class EmployeeRepository {
public void save(Employee employee) {
// Сохранение в базу
}
}
public class TaxCalculator {
public double calculateTax(Employee employee) {
// Расчет налогов
return employee.getSalary() * 0.13;
}
}
public class ReportGenerator {
public void generateReport(Employee employee) {
// Генерация отчета
}
}
OCP - Open-Closed Principle (Принцип открытости/закрытости)
Классы должны быть открыты для расширения, но закрыты для модификации.
Плохой пример:
public class AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.getRadius() * circle.getRadius();
} else if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
return rectangle.getWidth() * rectangle.getHeight();
}
throw new IllegalArgumentException("Unknown shape");
}
}
Хороший пример:
public interface Shape {
double calculateArea();
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class AreaCalculator {
public double calculateArea(Shape shape) {
return shape.calculateArea();
}
}
LSP - Liskov Substitution Principle (Принцип подстановки Лисков)
Объекты должны быть заменяемыми на экземпляры их подтипов без изменения правильности программы.
Плохой пример:
public class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
public class Square extends Rectangle {
@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width); // Нарушает поведение прямоугольника
}
@Override
public void setHeight(int height) {
super.setHeight(height);
super.setWidth(height); // Нарушает поведение прямоугольника
}
}
Хороший пример:
public interface Shape {
int getArea();
}
public class Rectangle implements Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public int getArea() {
return width * height;
}
}
public class Square implements Shape {
private int side;
public Square(int side) {
this.side = side;
}
@Override
public int getArea() {
return side * side;
}
}
ISP - Interface Segregation Principle (Принцип разделения интерфейсов)
Клиенты не должны зависеть от интерфейсов, которые они не используют.
Плохой пример:
public interface Worker {
void work();
void eat();
void sleep();
}
public class HumanWorker implements Worker {
public void work() { /* работа */ }
public void eat() { /* еда */ }
public void sleep() { /* сон */ }
}
public class RobotWorker implements Worker {
public void work() { /* работа */ }
public void eat() { /* робот не ест! */ }
public void sleep() { /* робот не спит! */ }
}
Хороший пример:
public interface Workable {
void work();
}
public interface Eatable {
void eat();
}
public interface Sleepable {
void sleep();
}
public class HumanWorker implements Workable, Eatable, Sleepable {
public void work() { /* работа */ }
public void eat() { /* еда */ }
public void sleep() { /* сон */ }
}
public class RobotWorker implements Workable {
public void work() { /* работа */ }
}
DIP - Dependency Inversion Principle (Принцип инверсии зависимостей)
Зависимости должны строиться на абстракциях, а не на деталях.
Плохой пример:
public class EmailService {
public void sendEmail(String message) {
// Отправка email
}
}
public class Notification {
private EmailService emailService;
public Notification() {
this.emailService = new EmailService(); // Жесткая зависимость
}
public void sendNotification(String message) {
emailService.sendEmail(message);
}
}
Хороший пример:
public interface MessageService {
void sendMessage(String message);
}
public class EmailService implements MessageService {
public void sendMessage(String message) {
// Отправка email
}
}
public class SMSService implements MessageService {
public void sendMessage(String message) {
// Отправка SMS
}
}
public class Notification {
private MessageService messageService;
// Внедрение зависимости через конструктор
public Notification(MessageService messageService) {
this.messageService = messageService;
}
public void sendNotification(String message) {
messageService.sendMessage(message);
}
}
// Использование
public class Main {
public static void main(String[] args) {
MessageService emailService = new EmailService();
Notification notification = new Notification(emailService);
notification.sendNotification("Hello!");
// Легко заменить на SMS
MessageService smsService = new SMSService();
Notification smsNotification = new Notification(smsService);
smsNotification.sendNotification("Hello via SMS!");
}
}
Практический пример с применением всех принципов
// SRP: Каждый класс имеет одну ответственность
// OCP: Легко добавить новые типы платежей
// LSP: Все платежные системы взаимозаменяемы
// ISP: Интерфейсы разделены по функциональности
// DIP: Зависимости от абстракций
public interface PaymentProcessor {
void processPayment(double amount);
}
public interface PaymentValidator {
boolean validatePayment();
}
public interface PaymentNotifier {
void sendNotification();
}
public class CreditCardPayment implements PaymentProcessor, PaymentValidator {
public void processPayment(double amount) {
// Обработка платежа по карте
}
public boolean validatePayment() {
// Валидация карты
return true;
}
}
public class PayPalPayment implements PaymentProcessor, PaymentNotifier {
public void processPayment(double amount) {
// Обработка PayPal платежа
}
public void sendNotification() {
// Отправка уведомления PayPal
}
}
public class PaymentService {
private PaymentProcessor paymentProcessor;
public PaymentService(PaymentProcessor paymentProcessor) {
this.paymentProcessor = paymentProcessor;
}
public void makePayment(double amount) {
paymentProcessor.processPayment(amount);
}
}
Эти принципы помогают создавать гибкий, поддерживаемый и расширяемый код, который легко тестировать и модифицировать.