Skip to content

Урок 12. SOLID

Принципы SOLID — это набор пяти принципов объектно-ориентированного программирования, которые помогают разработчикам создавать более гибкие, поддерживаемые и масштабируемые системы. Эти принципы были предложены Робертом Мартином (Robert C. Martin) и являются основой для хорошего проектирования программного обеспечения. Давайте рассмотрим каждый из принципов подробнее.

1. S - Single Responsibility Principle (SRP)

Принцип: Принцип единственной ответственности утверждает, что у класса должна быть только одна причина для изменения. Это означает, что класс должен иметь только одну ответственность или задачу.

Пример:

public class Report {
    public void generateReport() {
        // Логика генерации отчета
    }
}

public class ReportPrinter {
    public void printReport(Report report) {
        // Логика печати отчета
    }
}

В этом примере класс Report отвечает только за генерацию отчета, а класс ReportPrinter — за его печать. Это упрощает поддержку и тестирование.

2. O - Open/Closed Principle (OCP)

Принцип: Принцип открытости/закрытости утверждает, что классы должны быть открыты для расширения, но закрыты для модификации. Это означает, что вы должны иметь возможность добавлять новую функциональность, не изменяя существующий код.

Пример:

public abstract class Shape {
    public abstract double area();
}

public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double area() {
        return width * height;
    }
}

В этом примере вы можете добавлять новые фигуры, создавая новые классы, не изменяя существующий код.

3. L - Liskov Substitution Principle (LSP)

Принцип: Принцип подстановки Лисков утверждает, что объекты подкласса должны быть взаимозаменяемыми с объектами суперкласса. Это означает, что если класс S является подклассом класса T, то объекты типа T должны быть заменяемы объектами типа S без изменения правильности программы.

Пример:

public class Bird {
    public void fly() {
        System.out.println("Flying");
    }
}

public class Sparrow extends Bird {
    @Override
    public void fly() {
        System.out.println("Sparrow flying");
    }
}

public class Ostrich extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ostriches can't fly");
    }
}

В этом примере класс Ostrich нарушает принцип LSP, так как не может заменить Bird без изменения поведения программы. Лучше использовать интерфейсы или абстрактные классы для разделения поведения.

4. I - Interface Segregation Principle (ISP)

Принцип: Принцип разделения интерфейсов утверждает, что клиенты не должны зависеть от интерфейсов, которые они не используют. Это означает, что лучше создавать узкоспециализированные интерфейсы, чем один общий интерфейс.

Пример:

public interface Printer {
    void print();
}

public interface Scanner {
    void scan();
}

public class MultiFunctionPrinter implements Printer, Scanner {
    @Override
    public void print() {
        System.out.println("Printing");
    }

    @Override
    public void scan() {
        System.out.println("Scanning");
    }
}

В этом примере интерфейсы Printer и Scanner разделены, что позволяет создавать классы, которые реализуют только необходимые функции.

5. D - Dependency Inversion Principle (DIP)

Принцип: Принцип инверсии зависимостей утверждает, что высокоуровневые модули не должны зависеть от низкоуровневых модулей. Оба типа модулей должны зависеть от абстракций (например, интерфейсов). Это помогает уменьшить связанность между компонентами.

Пример:

```java public interface MessageService { void sendMessage(String message); }

public class EmailService implements MessageService { @Override public void sendMessage(String message) { System.out.println("Sending email: " + message); } }

public class Notification { private MessageService messageService;